Список C# <Интерфейс>: почему Вы не можете сделать 'Списка <IFoo> нечто = новый Список <Панель> ()';

Почему Вы должны? Атрибуты дают дополнительную информацию для отражения, но если Вы внешне знаете, какие свойства Вы хотите Вас, не нуждаются в них.

Вы могли сохранить метаданные внешне относительно легко в базе данных или файле ресурсов.

53
задан Cœur 14 August 2017 в 19:43
поделиться

8 ответов

На первый взгляд кажется, что этот должен (как в пиве должен быть бесплатным) работать. Однако быстрая проверка здравомыслия показывает нам, почему это невозможно. Имейте в виду, что следующий код не будет компилироваться . Он предназначен для того, чтобы показать, почему это не разрешено, хотя он выглядит нормально до определенного момента.

public interface IFoo { }
public class Bar : IFoo { }
public class Zed : IFoo { }

//.....

List<IFoo> myList = new List<Bar>(); // makes sense so far

myList.Add(new Bar()); // OK, since Bar implements IFoo
myList.Add(new Zed()); // aaah! Now we see why.

//.....

myList - это List , то есть может принимать любой экземпляр IFoo . Однако это противоречит тому факту, что он был создан как List . Поскольку наличие List означает, что я могу добавить новый экземпляр Zed , мы не можем этого допустить, поскольку базовый список на самом деле List , который может '

118
ответ дан 7 November 2019 в 08:18
поделиться

Причина в том, что C # не поддерживает ко- и контравариантность для универсальных шаблонов в C # 3.0 или более ранних версиях. Это реализовано в C # 4.0, поэтому вы сможете делать следующее:

IEnumerable<IFoo> foo = new List<Bar>();

Обратите внимание, что в C # 4.0 вы можете привести к IEnumerable , но вы не сможете привести к List . Причина связана с безопасностью типов, если вы могли привести List

39
ответ дан 7 November 2019 в 08:18
поделиться

Это связано с При создании списка вы указали, что T является IFoo, поэтому вы не можете создать его как Bar, поскольку они относятся к разным типам, хотя Bar поддерживает IFoo.

4
ответ дан 7 November 2019 в 08:18
поделиться

Список является типом в этом случае, и это не вопрос наследования. Список действительно отличается от List . List ничего не знает о IFoo или Bar и не наследует их.

Надеюсь, что это поможет.

1
ответ дан 7 November 2019 в 08:18
поделиться

List не наследуется от List

1
ответ дан 7 November 2019 в 08:18
поделиться

Поскольку список IFoo может содержать также несколько Bar , но список IFoo s ] - это не то же самое, что список Bar s.

Обратите внимание, что я использовал английский выше вместо C #. Хочу подчеркнуть, что это не серьезная проблема; вы просто запутались в деталях синтаксиса. Чтобы понять ответ, вам нужно выйти за пределы синтаксиса и подумать о том, что он на самом деле означает.

Список IFoo s может содержать Bar , потому что Bar также является IFoo . Здесь мы говорим об элементах списка. Список по-прежнему представляет собой список IFoo s. Мы этого не изменили.

Итак, список, который вы назвали foo , по-прежнему является списком IFoo s (более педантично, foo объявлен как List ) . Ничего другого и быть не может. В частности, его нельзя превратить в список Bar s ( List ). Список Bar - это совершенно другой объект, чем список IFoo s.

1
ответ дан 7 November 2019 в 08:18
поделиться

Если у вас есть список типа List , вы можете вызвать list.add (new Baz ()); предполагая, что Baz реализует IFoo . Однако вы не можете сделать это с помощью List , поэтому вы не можете использовать List везде, где можете использовать List .

Однако, поскольку Bar реализует IFoo ,

0
ответ дан 7 November 2019 в 08:18
поделиться

Если вам нужно преобразовать список в список базового класса или интерфейса, вы можете сделать это:

using System.Linq;

---

List<Bar> bar = new List<Bar>();
bar.add(new Bar());

List<IFoo> foo = bar.OfType<IFoo>().ToList<IFoo>();
10
ответ дан 7 November 2019 в 08:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: