[.NET] IList<T> en casten naar interfaces

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Ik begrijp de IList<T> niet in combinatie met het casten naar interfaces.

Een simpel voorbeeld:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface IPerson {
    string Name {
        get; set;
    }
}

public class Person : IPerson {
    private string name = "";

    public string Name {
        get {
            return name;
        }
    }
}


Met "normale" inheritance kan ik simpelweg het volgende doen:
C#:
1
2
IPerson person1 = new Person();
// Werkt omdat Person is afgeleid van IPerson


En vervolgens kan ik van een Person weer een IPerson maken
C#:
1
2
3
Person person2 = new Person();
IPerson casted = person2 as IPerson;
// Werkt omdat Person is afgeleid van IPerson


Nu merk ik dat bij IList<T> dit niet werkt en ik begrijp niet goed waarom niet.

C#:
1
2
3
IList<Person> persons = new List<Person>();
IList<IPerson> casted = persons as IList<IPerson>;
// casted is NULL


Waarom kan ik een IList<Person> niet gewoon naar een IList<IPerson> converteren?
Het rare is dat als ik de elementen benader en cast naar IPerson ze gewoon gecasted kunnen worden:
C#:
1
2
IPerson person = persons[0] as IPerson;
// Werkt perfect


Heeft iemand enig idee wat ik over het hoofd zie? Het lijkt er op alsof de IList<T> / List<T> niet aan de inheritance specificatie voldoen?

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 22:19
covariantie op generic parameters wordt niet ondersteund in C#3.5; wel in C# 4.0

http://msdn.microsoft.com/en-us/library/dd799517.aspx

http://blogs.msdn.com/csh...d-contravariance-faq.aspx

[ Voor 51% gewijzigd door whoami op 11-05-2010 15:53 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:28

.oisyn

Moderator Devschuur®

Demotivational Speaker

De reden is vrij logisch. Als jij een IList<IPerson> hebt, dan kun je daar elke IPerson aan toevoegen die je wilt. Ook die instanties die wel IPerson implementeren maar geen subklasse zijn van Person. Arrays zijn wat dat betreft een uitzondering (een Person[] kun je wel naar IPerson[] casten - een toekenning aan de array met iets dat geen Person is zal een exception gooien)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 05:47

Sebazzz

3dp

Heeft iemand enig idee wat ik over het hoofd zie? Het lijkt er op alsof de IList<T> / List<T> niet aan de inheritance specificatie voldoen?
Wel.
Stel dat dit zomaar kan in 3.5:
C#:
1
2
IList<Person> persons = new List<Person>();
IList<IPerson> casted = persons as IList<IPerson>; 

Dan doe ik dit:
C#:
1
2
3
class BlaatPerson : IPerson { ... }

casted.Add(new BlaatPerson());

Nu zit er een BlaatPerson in een Person lijst.

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Sebazzz schreef op dinsdag 11 mei 2010 @ 16:26:
[...]
Wel.
Stel dat dit zomaar kan in 3.5:
C#:
1
2
IList<Person> persons = new List<Person>();
IList<IPerson> casted = persons as IList<IPerson>; 

Dan doe ik dit:
C#:
1
2
3
class BlaatPerson : IPerson { ... }

casted.Add(new BlaatPerson());

Nu zit er een BlaatPerson in een Person lijst.
Echter is dat zoals gezegd inderdaad wel in contrast met Arrays, want daar compileert het volgende wel
C#:
1
2
3
Person[] persons = new Person[1];
IPerson[] casted = (IPerson[])persons;
casted[0] = new BlaatPerson();

Echter zal het nog steeds een runtime error geven. whoami geeft ook al meteen het keyword om op te zoeken: covariantie

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Wijnbo
  • Registratie: December 2002
  • Laatst online: 06-09 20:35

Wijnbo

Electronica werkt op rook.

Van hetzelfde laken een pak :
\[.NET] Waarom mag dit niet (inheritance)

Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 05:47

Sebazzz

3dp

Woy schreef op dinsdag 11 mei 2010 @ 16:56:
[...]

Echter zal het nog steeds een runtime error geven. whoami geeft ook al meteen het keyword om op te zoeken: covariantie
Is dat een compiler fout? Of stamt een T[] van een Array af?

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:28

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het is gewoon by design. Java doet het ook. Overigens kan het weer niet met arrays van value types, alleen met arrays van reference types.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Face_-_LeSS
  • Registratie: September 2004
  • Niet online
Je weet nu waarom maar mocht je een IList<Person> willen casten naar een IList<IPerson> dan kan dat eenvoudig door:

C#:
1
2
            IList<Person> persons = new List<Person>();
            IList<IPerson> casted = persons.Cast<IPerson>().ToList();


Voor het geval je dat nog niet wist ;)
Pagina: 1