C# .Net Covariance - еще раз для старых времен?

Итак, у нас есть это:

public interface IWidget
{
    int Id { get; set; }
}

public class Widget : IWidget
{
    public int Id { get; set; }
}

public class WidgetProcessor
{
    public static void ProcessWidgets1(IList<IWidget> widgets)
    { }

    public static void ProcessWidgets2<T>(IList<T> widgets) where T : IWidget
    { }
}

Я понимаю, почему это не скомпилируется: WidgetProcessor.ProcessWidgets1(new List<Widget>()); В C# правила ковариации мудро говорят, что не должны, или вы можете столкнуться со всевозможными глупостями, как подробно объяснялось в другом месте.

Но ProcessWidgets2: что за...?
Как получается, что это компилируется и запускается: WidgetProcessor.ProcessWidgets2(new List<Widget>());

С нетерпением жду удаления моего невежества, но я не вижу, как ProcessWidgets1 и ProcessWidgets2 (эффективно) отличаются.

2 ответа

Решение

ProcessWidgets2<T> это общий метод. Когда вы звоните с new List<Widget>()компилятор делает вывод, что тип T является Widget, который соответствует ограничениям, и вызывает его, так как List<T> инвентарь IList<T>,

Потенциально проще всего смотреть на него так, как будто он разбит на несколько вызовов:

IList<Widget> temp = new List<Widget>();
WidgetProcessor.ProcessWidgets2<Widget>(temp); // Widget is an IWidget, so this matches constraints

Здесь нет различий в игре, так как List<T> непосредственно реализует IList<T>и вы вызываете с определенным типом, который выводится компилятором.

В первом примере вы можете выполнить код:

widgets.Add(new SomeOtherWidget());

Если widgets на самом деле было разрешено быть List<Widget> тогда вы бы положили SomeOtherWidget в список Widget объекты. Это было бы плохо, так как, когда вы достали объект, это может быть не Widget совсем.

Со вторым примером, widgets.Add(new SomeOtherWidget()); не скомпилируется. SomeOtherWidget не будет типа T, Вам будет разрешено только позвонить Add в списке с объектом типа T, а не любой старый IWidget объект, поэтому он может поддерживать безопасность типов.

Другие вопросы по тегам