C # Ссылка понимание? - PullRequest
       24

C # Ссылка понимание?

4 голосов
/ 04 февраля 2012

если у меня есть:

   public class A {   public int a1;}
   public class B : A {  public int b1;}

   void myFunc(A a) 
   {}

  static void Main(string[] args)
       {
         B b = new B();
         myFunc(b);
       }

in myFunc, a может получить доступ к b объекту, но может ссылаться только (без приведения) на область в памяти, которая является type A.

это понятно.

Однако в ковариация кажется, что a может также получить доступ к b: enter image description here

Как вы можете видеть - он принимает Enumerable из A и по-прежнему может обращаться к своим B типизированным объектам


вопросы:

1 ) Хорошо, как за кадром это работает? как ссылка A может показать мне larger объект?

2 ) Что если я хотел бы увидеть в функции свойство a1 из класса A? Что мне изменить?

редактировать

Ковариация связана:

До C # 4 вы не могли пройти в List: не может конвертировать из 'System.Collections.Generic.List' для 'System.Collections.Generic.IEnumerable'

Пример ковариации и контравариантности в реальном мире

Ответы [ 3 ]

6 голосов
/ 04 февраля 2012

Как ссылка может показать мне объект большего размера?

Во-первых, это меньше типа. Каждый жираф - это животное, но не каждое животное - это жираф. Поэтому в мире меньше жирафов, чем животных в мире. Поэтому жираф - меньший тип, чем животное.

Ваш тип B является меньшим типом, чем А. И, конечно, ссылка на больший тип может относиться к чему-то меньшего типа.

Это не имеет ничего общего с ковариацией. Это всегда тот случай, когда IEnumerable<A> может дать вам B:

List<A> myList = new List<A>() { new B(); } // No covariance here
Console.WriteLine(myList[0].GetType()); // it's a B.

Список животных может содержать жирафа. Это не имеет ничего общего с ковариацией.

Точно так же ссылка всегда может вернуть вам меньший тип:

A a = new B(); // Legal!

тем, кто говорит, что это не имеет ничего общего с ковариацией ...

То, что последовательность A может содержать a B, не имеет ничего общего с ковариацией. Что касается ковариации, то последовательность B может быть преобразована в последовательность A путем преобразования ссылок. До того, как ковариантные преобразования были добавлены в C # 4, это преобразование не удалось бы.

Что если бы я хотел увидеть в функции свойство a1 из класса A? что я должен изменить?

Вы не должны ничего менять; это уже работает. Попробуй.

5 голосов
/ 04 февраля 2012

Как видите, он принимает Enumerable из A и по-прежнему может обращаться к своим типизированным объектам B

Отладчик показывает его как B, потому что видит, что его фактический тип - BКод в myFunc может получить доступ только к членам A, если только он не приводит объект к B.

0 голосов
/ 04 февраля 2012

myFunc видит тип B, потому что вы называете его одним из myFunc(b);

Вы видите a1 внутри базового класса A

Если вы делаете

static void Main(string[] args)
       {
         A a = new A();
         myFunc(a);
       }

Вы непосредственно увидите тип A

Редактировать

Просто чтобы прояснить это:

void myFunc(A a) 

следует читать как

void myFunc({Either A or something "larger" than A} a) 

с "большим" значением "наследование"

...