Причина определенных ограничений на преобразования дисперсии в C # -- c# поле с участием delegates поле с участием implicit-conversion поле с участием contravariance поле с участием generic-variance пол Связанный проблема

Reason for certain restrictions on variance conversions in C#


0
vote

проблема

русский

У меня есть несколько вопросов о том, как неявные преобразования между методом делегатов в отношении ковариации и контравариации реализуются в C #.

 <код> delegate void ImplicitFunction<T>(T thing); delegate void ExplicitFunction<in T>(T thing); delegate void AnimalFunction(Animal thing); delegate void DogFunction(Dog thing);  static void Process<T>(T thing) {     // ... } static void AnimalProcess(Animal thing) {     // ... }  static void Main() {   

от моего понимания, обработка дисперсии неявно в отношении назначения Функция на не идентичный делегат, то есть.:

 <код>     ImplicitFunction<Dog> processObject = Process<Animal>;   

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

 <код>     ImplicitFunction<Animal> tempProcessor = Process<Animal>;     ImplicitFunction<Dog> processDogConv = tempProcessor; // compile error   

Вопрос 1: почему нет? И, пожалуйста, не говорите, «Потому что вы не используете« в »или« потому что это не является общим типом ». Я хотел бы знать Что обоснование для такого поведения, так же, как ограничения дисперсии на месте, чтобы предотвратить прохождение недействительных типов в определенные случаи. Теперь я также узнал, что C # поддерживает Явное преобразование делегата с использованием ключевых слов 'и из'. Как так:

 <код>     ExplicitFunction<Animal> processAnimal = Process<Animal>;     ExplicitFunction<Dog> processDog = processAnimal;   

Но я не могу сделать то же самое без родов:

 <код>     AnimalFunction processAnimalNonGeneric = AnimalProcess;     DogFunction processDogNonGeneric = processAnimalNonGeneric; // compile error   

У меня есть чувство причины этого может быть тесно связаны с причиной того, что неявна Переменные преобразования не поддерживаются.

Вопрос 2: Но почему? Почему я не могу использовать «в» Ключевое слово что-то вроде так:

 <код> delegate void AnimalFunction(in Animal thing); delegate void DogFunction(in Dog thing);   

еще раз, я знаю, что просто не как это работает, но что такое теоретический, «Мы не можем-потому что-что-если-кто-кто-это сделал-это» Причина для исключения этой функциональности?

 <код> }   

P.S. Этот код был составлен, чтобы убедиться, что он ведет себя, как я опишу, и все, что нужно, - это класс обертки и два пустых Dog : Animal классов.

Английский оригинал

I have a few questions about the way implicit conversions between method delegates with regards to covariance and contravariance are implemented in C#.

delegate void ImplicitFunction<T>(T thing); delegate void ExplicitFunction<in T>(T thing); delegate void AnimalFunction(Animal thing); delegate void DogFunction(Dog thing);  static void Process<T>(T thing) {     // ... } static void AnimalProcess(Animal thing) {     // ... }  static void Main() { 

From my understanding, variance handling is implicit with regards to assigning a function to a non-identical delegate, i.e.:

    ImplicitFunction<Dog> processObject = Process<Animal>; 

(Conceptually, although possibly not semantically, I believe this is contravariance. Of course, if any of my assumptions are completely wrong, I would appreciate a correction.) After many hours of careful studying, I believe I completely understand how this works and why. But I have also learned that I cannot convert a method from one type (delegate) to another, even though it is assigning the same value to the same type, just in two steps:

    ImplicitFunction<Animal> tempProcessor = Process<Animal>;     ImplicitFunction<Dog> processDogConv = tempProcessor; // compile error 

Question 1: why not? And please do not say, "because you do not use 'in'" or "because it is not a generic type". I would like to know what the justification is for this behavior, in the same way that variance restrictions are in place to prevent passing invalid types in certain cases. Now, I have also learned that C# supports explicit delegate conversion using the keywords 'in' and 'out'. Like so:

    ExplicitFunction<Animal> processAnimal = Process<Animal>;     ExplicitFunction<Dog> processDog = processAnimal; 

But I can't do the same thing without generics:

    AnimalFunction processAnimalNonGeneric = AnimalProcess;     DogFunction processDogNonGeneric = processAnimalNonGeneric; // compile error 

I have a feeling the reason for this may be closely related to the reason that implicit variance conversions are not supported.

Question 2: But why? Why can't I use the 'in' keyword something like so:

delegate void AnimalFunction(in Animal thing); delegate void DogFunction(in Dog thing); 

Once again, I know that just isn't how it works, but what is the theoretical, "we-can't-because-what-if-someone-did-this" reason for excluding this functionality?

} 

P.S. This code has been compiled to make sure it behaves as I describe, and all that is needed is a wrapper class and two empty Dog : Animal classes.

</div
              
         
         

Список ответов

Связанный проблема

105  Почему C # реализует методы как не виртуальные по умолчанию?  ( Why c sharp implements methods as non virtual by default ) 
В отличие от Java, почему C # методы лечения как не виртуальные функции по умолчанию? Скорее всего, это проблема производительности, а не на других возможных ...

0  Написание одного символа за раз в приложении консоли C #?  ( Writing one character at a time in a c sharp console application ) 
Я не уверен, как это объяснить ... В основном я хочу иметь возможность писать строки текста в консоли, как старые RPG, используемые для записи диалога, один...

0  C # Исключение, где емкость ниже, чем количество  ( C sharp exception where capacity is lower than count ) 
Я ударю исключение со списком в C #, когда добавляю элемент в списке. Я не могу видеть ничего конкретного там. <Код> tempList.ForEach(tempDis => alloc.ListD...

8  Почему я не могу удалить это cookie?  ( Why cant i delete this cookie ) 
Хорошо, вот 411 - у меня есть следующий обработчик событий в моем файле Global.Asax.cs: <код> private void Global_PostRequestHandlerExecute(object sender, E...

9  DataTable не выпускает память  ( Datatable does not release memory ) 
У меня есть процесс загрузки данных, который загружает большую сумму данных в DataTable, затем выполняет некоторые данные, но каждый раз, когда задание заверш...

0  Получить объект атрибута из inamedtypesymbol.getttributes () I.e. Объект Attribradate?  ( Get attribute object from inamedtypesymbol getattributes i e attributedata ob ) 
Я определил следующий атрибут <код> [AttributeUsage(AttributeTargets.Class)] class DemoAttribute : Attribute { public string SomeInfo { get; } public D...

1  EntityFramework 5 CodeFirst Rice родитель одного типа не обновляет / сохранение  ( Entityframework 5 codefirst child parent of the same type not updating saving ) 
У меня есть <код> class называется раздел <код> public class Section { public Section() { construct(0); } public Section(int order) { construct(ord...

0  Обновление данных с той же первичным ключом  ( Updating data with same primary key ) 
Я читаю данные из файла CSV и добавление данных в базу данных. Во время вставки данных в базу данных я хочу обновить данные с той же первичной клавишей. e.g...

5  Объект к сопоставлению объекта  ( Object to object mapping utility ) 
Мне нравится чисто разделить публику и домен объекты (Итак, nhibernate не поможет здесь) друг от друга, которые заставляют меня писать много кода, чтобы ото...

0  WCF Post Method Получить ошибку 400 плохой запрос  ( Wcf post method get error 400 bad request ) 
Я использую метод WCF Post, как только я добавил PARAMETER POST на службу, его ошибка возврата 400 плохой запрос, если я оставил параметр пустой, он может пол...

-1  Какой поток Nibernate Pure? [закрыто]  ( What is the flow of nhibernate pure ) 
<в сторону CLASS = "S-NEWACTS S-WELTIVE__info JS-Post-New Imide MB16« Роль = «Статус»> закрыт . Этот вопрос должен быть больше Фокусированный . В настоя...

0  Ресурс кастинга COSMOS БД в интерфейс  ( Cosmos db casting resource to interface ) 
Если я хочу вернуть объект на основе интерфейса в Cosmodb, как бы я это сделал? Мой интерфейс: <код> namespace Test { public interface IPerson { ...

1  Как получить доступ к конкретной группе в CollectionSourceSource.View.Groups  ( How to access a specific group within collectionviewsource view groups ) 
У меня есть .NET Имя Свойство. Я хотел бы знать, есть ли способ выбрать определенную подгруппу на достаточно высоком уровне без необходимости оценивать н...

1  Visual Studio C # KeyDown блокирует друг друга  ( Visual studio c sharp keydown blocking each other ) 
Есть ли способ сделать два ключа работать одновременно, поэтому они не блокируют друг друга? <код> private void multiplayer_KeyDown(object sender, KeyEv...

1  WCF Callback Doblocks даже с «iSineynchronInationContext = False»  ( Wcf callback deadlocks even with usesynchronizationcontext false ) 
Я застрял с проблемой, которую я не могу понять. Проблема связана с синхронизацией между потоками на стороне клиента, но я не могу найти корневую причину эт...