@NikVladi

Почему нужны ключевые слова in и out в универсальных вариантных делегатах с типами которых содержатся события в универсальных вариантных интерфейсах?

Спрашивал на разных ресурсах, в последней инстанции тут https://github.com/dotnet/docs/issues/25233 дали ответ, но это догадки и они неубедительны.

Вопрос:
Как я понимаю, ключевые слова in и out в универсальных вариантных делегатах нужны только чтобы назначить один делегат другому. Для назначения методов вариантность есть и без ключевых слов in и out.

Источник https://docs.microsoft.com/ru-ru/dotnet/csharp/pro...
Цитата: Если поддержка вариантности используется только для сопоставления сигнатур методов с типами делегатов, а ключевые слова in и out не используются, можно создать экземпляры делегатов с одинаковыми лямбда-выражениями или методами, но нельзя назначить один делегат другому.

Почему я не могу сделать то же самое (назначать только методы), но через универсальный вариантный интерфейс? И мне приходится писать в объявлении делегата ключевое слово (in или out).

Например,

namespace ConsoleApp1 {
  class Program {
    static void Main(string[] args) {
      //Шаг 1
      B MyMethodReturnB() {
        return new B();
      }

      //Шаг 2
      MyClass<A> MyClassForA = new MyClass<A> ();
      MyClassForA.MyEvent += MyMethodReturnB; //В MyClass< A >() вы можете поместить данные типа B с помощью метода MyMethodReturnB и без ключевого слова out в делегате MyDelegateReturn

      //Шаг 3
      MyDelegateReturn<B> MyDelegateReturnForB = new MyDelegateReturn<B>(MyMethodReturnB);
      //MyClassForA.MyEvent += MyDelegateReturnForB; //Но когда мы пытаемся передать данные типа B через переменную делегата без ключевого слова out, возникает ошибка, так вариантность работает в делегатах.
      //Без ключевых слов in и out один делегат не может быть назначен другому делегату

      //Шаг 4
      IMyInterface<B> IMyInterfaceForB = MyClassForA; //Через интерфейс IMyInterface< B > без ключевого слова in вы не можете поместить MyClass< A >(), но если IMyInterface< B > с ключевым словом in, то мы можем

      //Шаг 5
      //Как только мы создадим интерфейс с ключевым словом in, потребуется делегат с ключевым словом out, почему?
      //В конце концов, delagate без ключевого слова out каким-то образом имеет ковариацию, но только для методов, а не экземпляров делегата, что означает, что я мог бы в любом случае поместить метод в событие, но не экземпляр делегата. Но мы не можем этого сделать
    }
  }

  class A {

  }

  class B: A {

  }

  delegate T MyDelegateReturn</*out*/ T>(); //С ключевым словом out все работает

  interface IMyInterface<in T>{
    event MyDelegateReturn<T> MyEvent; //Ошибка из-за делегата без ключевого слова out
  }

  class MyClass<T>: IMyInterface<T> {
    public event MyDelegateReturn<T> MyEvent;
  }
}
  • Вопрос задан
  • 142 просмотра
Пригласить эксперта
Ответы на вопрос 1
Спрашивал на разных ресурсах, в последней инстанции тут https://github.com/dotnet/docs/issues/25233 дали ответ, но это догадки и они неубедительны.

Боюсь, тут вам лучше ответить не смогут, тк тут нет людей, кто хотябы знаком с автором этой фичи.
Так что мой ответ: "Так исторически сложилось"
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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