2009-11-21 18 views
8

Poniższe jest zgodne, ale w czasie wykonywania zgłasza wyjątek. Próbuję rzucić klasę PersonWithAge na klasę Person. Jak to zrobić i na czym polega praca?Przesyłaj/przeliczaj IEnumerable <T> na IEnumerable <U>?

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: Przy okazji PersonWithAge zawsze zawierają te same właściwości jak osoby plus kilka innych.

EDIT 2 Sorry chłopaki ale powinien zrobiłem to nieco wyraźniej, że mam dwa db widoki w bazie danych, która zawiera te same kolumny, ale widok 2 zawiera 1 dodatkowe pole. Moje jednostki widoku modelu generowane są przez narzędzie, które naśladuje widoki bazy danych. Mam częściowy widok MVC, który dziedziczy po jednej z encji klasowych, ale mam więcej niż jeden sposób przechwytywania danych ...

Nie jestem pewien, czy to pomaga, ale oznacza to, że nie mogę sprawić, by osobaWithAge dziedziczyła od osoby.

Odpowiedz

16

Nie można rzucić, bo są różne rodzaje. Masz dwie możliwości:

1) Zmień klasę tak, aby PersonWithAge dziedziczyła od osoby.

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

2) tworzenia nowych obiektów:

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

Wybrana droga może być drogą do przodu, jednak oczekiwałbym kary, ponieważ nie musi to być droga szczupła. – Rippo

6

Zastosowanie Select zamiast Cast w celu wskazania, jak wykonać konwersję z jednego typu na inny:

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

także PersonWithAge zawsze będzie zawierać te same właściwości jak Person plus kilka bardziej byłoby lepiej aby odziedziczyć po Person.

+0

select sposób może być droga do przodu, jednak spodziewałbym się kary za to nie może być chudy sposób. – Rippo

1

możesz zmodyfikować kod, aby być coś takiego:

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

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

Złóż PersonWithAge dziedziczą osoby.

Jak to:

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

Nie można po prostu rzucać dwóch niepowiązanych typ do siebie. Możesz umożliwić przekształcenie PersonWithAge w Person przez umożliwienie PersonWithAge dziedziczenia z Person. Od PersonWithAge jest oczywiście szczególny przypadek osoby, to sprawia, że ​​wiele sensu:

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; } 
} 

Teraz jeśli masz IEnumerable<PersonWithAge> nazwie personsWithAge, następnie personsWithAge.Cast<Person>() zadziała.

w VS 2010 będzie nawet w stanie rzucić zupełnie pominąć i zrobić (IEnumerable<Person>)personsWithAge, ponieważ IEnumerable<T> jest kowariantna w .NET 4.

1

Możesz zachować IEnumerable<PersonWithAge> i nie przekształcić go IEnumerable<Person>. Po prostu dodaj niejawną konwersję, aby przekonwertować obiekt z PersonWithAge na Person, gdy zajdzie taka potrzeba.

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]; 
Powiązane problemy