13

The following complies but at run time throws an exception. What I am trying to do is to cast a class PersonWithAge to a class of Person. How do I do this and what is the work around?

class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class PersonWithAge
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<PersonWithAge> pwa = new List<PersonWithAge>
        {
            new PersonWithAge {Id = 1, Name = "name1", Age = 23},
            new PersonWithAge {Id = 2, Name = "name2", Age = 32}
        };

        IEnumerable<Person> p = pwa.Cast<Person>();

        foreach (var i in p)
        {
            Console.WriteLine(i.Name);
        }
    }
}

EDIT: By the way PersonWithAge will always contain the same properties as Person plus a couple more.

EDIT 2 Sorry guys but I should have made this a bit clearer, say I have two db views in a database that contains the same columns but view 2 contains 1 extra field. My model view entities are generated by a tool that mimics the database views. I have a MVC partial view that inherits from one of the class entities but I have more than one way to grab data...

Not sure if this helps but it means that I cant make personWithAge inherit from person.

TrueWill
  • 24,482
  • 7
  • 94
  • 140
Rippo
  • 21,356
  • 13
  • 72
  • 115

6 Answers6

19

You can't cast because they are different types. You have two choices:

1) Change the class so that PersonWithAge inherits from person.

class PersonWithAge : Person
{
        public int Age { get; set; }
}

2) Create new objects:

IEnumerable<Person> p = pwa.Select(p => new Person { Id = p.Id, Name = p.Name });
Mark Byers
  • 767,688
  • 176
  • 1,542
  • 1,434
8

Use Select instead of Cast in order to indicate how to perform the conversion from one type to another:

IEnumerable<Person> p = pwa.Select(x => new Person { Id = x.Id, Name = x.Name });

Also as PersonWithAge will always contain the same properties as Person plus a couple more it would be better to have it inherit from Person.

Darin Dimitrov
  • 994,864
  • 265
  • 3,241
  • 2,902
5

You can't just cast two unrelated type into each other. You could make it possible to convert PersonWithAge to Person by letting PersonWithAge inherit from Person. Since PersonWithAge is obviously a special case of a Person, this makes plenty of sense:

class Person
{
        public int Id { get; set; }
        public string Name { get; set; }
}

class PersonWithAge : Person
{
        // Id and Name are inherited from Person

        public int Age { get; set; }
}

Now if you have an IEnumerable<PersonWithAge> named personsWithAge, then personsWithAge.Cast<Person>() will work.

In VS 2010 you will even be able to skip the cast altogether and do (IEnumerable<Person>)personsWithAge, since IEnumerable<T> is covariant in .NET 4.

Joren
  • 14,084
  • 3
  • 49
  • 53
3

Make PersonWithAge inherit from Person.

Like this:

class PersonWithAge : Person
{
        public int Age { get; set; }
}
Michał Drozdowicz
  • 1,234
  • 11
  • 30
1

you might want to modify your code to be something like:

class Person
{
        public int Id { get; set; }
        public string Name { get; set; }
}

class PersonWithAge : Person
{
        public int Age { get; set; }
}
John Boker
  • 80,803
  • 17
  • 95
  • 130
1

You can keep the IEnumerable<PersonWithAge> and don't convert it to IEnumerable<Person>. Just add an implicit conversion to convert an object of PersonWithAge to Person when you need.

class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public static implicit operator Person(PersonWithAge p)
    {
        return new Person() { Id = p.Id, Name = p.Name };
    }
}

List<PersonWithAge> pwa = new List<PersonWithAge>
Person p = pwa[0];
Mehdi Golchin
  • 7,733
  • 2
  • 29
  • 36