Search code examples
c#csharpcodeprovider

C# Casting Array and getting information out of an array of objects


I am trying to see if I can cast a menu object as food. I will be putting in the interface as I have been advised.

In my buffet code where my Food method is called after adding all the stuff to the menu object, my goal is to pick a random food to eat then return the information.

I was hoping that I could do something like where I got the mo =(Food) Menu[rand.Next(Menu.Count)]; would allow me to this easily.

I was wrong, I might be overcomplicating this because I was going to return mo but every time I try to cast it, it did not work.

Maybe I can use an enumerator or something but it is just very confusing. I think I have the proper thinking of what I want but to express in words is difficult so thank you all for your patience with me. I hope this explains it better:

my Buffet class

using System;
using System.Collections.Generic;


namespace IronNinja.Models
{
    
    class Buffet
    {
        public List<Food> Foods = new List<Food>();

        public List<Drink> Dranks = new List<Drink>();

        public List<object> Menu = new List<object>();

        //constructor
        public Buffet()
        {
            Menu.Add(new Food("Chicken Pizza", 1000, false, true));
            Menu.Add(new Food("Buffalo Chicken Pizza", 1000, true, false));
            Menu.Add(new Food("Lasagna", 1200, false, true));
            Menu.Add(new Food("Garden Salad WSalad dressing", 700, true, false));
            Menu.Add(new Food("sour patch kids whole box", 700, false, true));
            Menu.Add(new Drink("Rootbeer", 700, false));
            Menu.Add(new Drink("Not Your Father's Rootbeer", 900, false));
        }
        // Add a constructor and Serve method to the Buffet class
        public Food Serve()
        {
            Random rand = new Random();
            Food mo =  ((Food) Menu[rand.Next(Menu.Count)]);
            Console.WriteLine(mo);

            return new Food("sour patch kids whole box", 700, false, true);
        }
    }
}

My Drink class

using IronNinja.Interfaces;
namespace IronNinja.Models
{
    public class Drink : IConsumable
    {
        public string Name { get; set; }
        public int Calories { get; set; }
        public bool IsSpicy { get; set; }
        public bool IsSweet { get; set; }
       // Implement a GetInfo Method
        public string GetInfo()
        {
            return $"{Name} (Drink).  Calories: {Calories}.  Spicy?: {IsSpicy}, 
             Sweet?: {IsSweet.Equals(true)}";
        }
        // Add a constructor method
        public Drink(string name, int calories, bool spicy)
        {
            Name = name;
            Calories = calories;
            IsSpicy = spicy;
            IsSweet = true;
        }
    }
}

my foodclass

using IronNinja.Interfaces;
namespace IronNinja.Models
{
    class Food : IConsumable
    {
        public string Name { get; set; }
        public int Calories { get; set; }
        public bool IsSpicy { get; set; }
        public bool IsSweet { get; set; }
        public string GetInfo()
        {
            return $"{Name} (Food).  Calories: {Calories}.  Spicy?: {IsSpicy}, 
            Sweet?: {IsSweet}";
        }
        public Food(string name, int calories, bool spicy, bool sweet)
        {
            Name = name;
            Calories = calories;
            IsSpicy = spicy;
            IsSweet = sweet;
        }
    }
}

Solution

  • UPDATE

    If you just want to grab a random item that is a food, you can use a Linq expression to get all items that are of the type Food.

    Random rand = new Random();
    var foodItems = Menu.OfType<Food>().ToList();
    var randomFood = foodItems[rand.Next(foodItems.Count)];
    

    I would create an interface called IMenuItem that has the shared properties for every type that goes on a menu.

    public interface IMenuItem
    {
        string Name { get; }
    }
    

    Then add that interface to your Food and Drink classes

    public class Food : IMenuItem
    {
        public Food(string name, int calories, bool isSpicy, bool isSweet)
        {
            Name = name;
            Calories = calories;
            IsSpicy = isSpicy;
            IsSweet = isSweet;
        }
    
        public string Name { get; }
        public int Calories { get; }
        public bool IsSpicy { get; }
        public bool IsSweet { get; }
    }
    
    public class Drink: IMenuItem
    {
        public Drink(string name, int calories, bool isSpicy)
        {
            Name = name;
            Calories = calories;
            IsSpicy = isSpicy;
        }
    
        public string Name { get; }
        public int Calories { get; }
        public bool IsSpicy { get; }
    }
    

    Now you can have a list of menu items and you will be able to access those shared properties without having to cast anything.

    var menu = new List<IMenuItem>();
    menu.Add(new Food("pizza", calories: 300, isSpicy: false, isSweet: true));
    menu.Add(new Drink ("coke", calories: 300, isSpicy: false));
    
    foreach(var menuItem in menu)
    {
        Console.WriteLine(item.Name);
    }
    

    output

    pizza
    coke
    

    Also, you can use pattern matching to do things based on what type it actually is.

    var menu = new List<IMenuItem>();
    menu.Add(new Food("pizza", calories: 300, isSpicy: false, isSweet: true));
    menu.Add(new Drink("coke", calories: 300, isSpicy: false));
    
    // get random menu item;
    var rand = new Random();
    var menuItem = menu[rand.Next(menu.Count)];
    
    switch (menuItem)
    {
        case Food food: // random item is a food
            Console.WriteLine($"Food Name:{food.Name}, Calories:{food.Calories}, IsSpicy:{food.IsSpicy}, IsSweet:{food.IsSweet}");
            break;
        case Drink drink: // random item is a drink
            Console.WriteLine($"Drink Name:{drink.Name}, Calories:{drink.Calories}, IsSpicy:{drink.IsSpicy}");
            break;
        default: // random item is something else
            Console.WriteLine($"Menu Item Name:{menuItem.Name}");
            break;
    }