15

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
  • 25,132
  • 10
  • 101
  • 150
Rippo
  • 22,117
  • 14
  • 78
  • 117

6 Answers6

21

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
  • 811,555
  • 193
  • 1,581
  • 1,452
9

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
  • 1,023,142
  • 271
  • 3,287
  • 2,928
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,472
  • 3
  • 50
  • 54
3

Make PersonWithAge inherit from Person.

Like this:

class PersonWithAge : Person
{
        public int Age { get; set; }
}
Michał Drozdowicz
  • 1,232
  • 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
  • 82,559
  • 17
  • 97
  • 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];
m3kh
  • 7,881
  • 2
  • 31
  • 37