1

I implement a WindowsForms application in Visual Studio. Now I have a list of toys:

List <Toy> toys;

Toy is an abstract class, and classes like Car, Submarine etc. derive from it. The list can of course contain any object of type Toy. Due to my lack of experience in C#, I'm not sure how can I modify an object from this list, i. e. change a property that is type-specific. The compiler only knows the list contains Toy objects, and has no access to fields of a Submarine object. So I cannot simply take some element from the list, call a setter and be done with it. Casting will only get me a copy of the list object cast to some type. How can I achieve this?

Michał Szydłowski
  • 3,261
  • 5
  • 33
  • 55

4 Answers4

2

If you're not savvy with Lync or want to do more with the item, you can also do it the 'old school' way in a loop.

Given the sample classes:

public abstract class Toy
{
    public string Manufacturer { get; set; }
}

public class Elephant : Toy
{
    public int TrunkLength { get; set; }
}

public class Car : Toy
{
    public Color Color { get; set; }
}

You can do something like this to add the items and then modify them based on their type:

var toys = new List<Toy>
{
    new Car {Color = Color.Red, Manufacturer = "HotWheels"},
    new Elephant {TrunkLength = 36, Manufacturer = "Steiff Harlequin"}
};

foreach (var toy in toys)
{
    var car = toy as Car;
    if (car != null)
    {
        // Set properties or call methods on the car here
        car.Color = Color.Blue;

        // Continue the loop
        continue;
    }

    var elephant = toy as Elephant;
    if (elephant != null)
    {
        // Do something with the elephant object
        elephant.TrunkLength = 48;

        // Continue the loop
        continue;
    }
}

Or you could use a 'switch' statement and some casting, which may be more readable:

foreach (var toy in toys)
{
    switch (toy.GetType().Name)
    {
        case "Car":
            ((Car) toy).Color = Color.Blue;
            break;
        case "Elephant":
            var elephant = toy as Elephant;
            elephant.TrunkLength = 48;
            elephant.Manufacturer = "Made in China";
            break;
    }
}
Rufus L
  • 36,127
  • 5
  • 30
  • 43
1

You have to cast items :

Engine door = toys.OfType<Car>().Select(c => c.Engine).FirstOrDefault();
rducom
  • 7,072
  • 1
  • 25
  • 39
1

So... You basically have a situation like this?

public abstract class Toy 
{ 
}

public class Submarine : Toy 
{ 
    public bool IsOccupiedByPretendPeople { get; set; } 
} 

And you also have

List<Toy> toys;

And you want to get all the instances of a Submarine class?

This should do the trick:

IEnumerable<Submarine> submarines = toys.OfType<Submarine>();

If you posted an example of your Toy class (as mentioned in the comments of your question), I could further assist you with what you're trying to accomplish.

Cameron
  • 2,574
  • 22
  • 37
1

When we have an inheritance family and we need to use specific feature from one of the subtypes we can also use the is operator: here is an example

public abstract class Toy { }

public class Submarine : Toy
{
}

public class Airwolf : Toy
{

    public Boolean ActivateMissiles()
    {
        return true;
    }

}
class Program
{
    static void Main(string[] args)
    {
        List<Toy> myToys = new List<Toy>();
        myToys.Add(new Submarine());
        myToys.Add(new Airwolf());

        // Looking for airwolves
        foreach (Toy t in myToys)
        {
            if (t is Airwolf)
            {
                Airwolf myWolf = (Airwolf)t;
                myWolf.ActivateMissiles();
            }
        }
    }
}
alainlompo
  • 4,414
  • 4
  • 32
  • 41
  • It's recommended to use `as` plus `!= null` check over `is`. For more info, check the answer here: http://stackoverflow.com/questions/2139798/does-it-make-sense-to-use-as-instead-of-a-cast-even-if-there-is-no-null-check – Rufus L Feb 13 '15 at 23:11