N
N
NikVladi2021-07-22 07:17:23
C++ / C#
NikVladi, 2021-07-22 07:17:23

Why are the in and out keywords needed in generic variant delegates whose types contain events in generic variant interfaces?

I asked on various resources, in the last resort here https://github.com/dotnet/docs/issues/25233 gave an answer, but these are guesses and they are unconvincing.

Question:
As far as I understand, the in and out keywords in generic variant delegates are only needed to assign one delegate to another. For assigning methods, there is variance even without the in and out keywords.

Source https://docs.microsoft.com/en-us/dotnet/csharp/pro...
Quote: If variance support is used only to map method signatures to delegate types, and the in and out keywords are not used, instances can be created delegates with the same lambda expressions or methods, but you cannot assign one delegate to another.

Why can't I do the same (assign only methods) but through a generic variant interface? And I have to write a keyword (in or out) in the delegate declaration.

For example,

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;
  }
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vasily Bannikov, 2021-07-22
@vabka

I asked on various resources, in the last resort here https://github.com/dotnet/docs/issues/25233 gave an answer, but these are guesses and they are unconvincing.

I’m afraid they won’t be able to answer you better here, because there are no people here who are at least familiar with the author of this feature.
So my answer is: "So it happened historically"

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question