关于协变和逆变的方法委托之间的隐式转换在 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:为什么不呢?并且请不要说“因为你不使用'in'”或“因为它不是泛型类型”。我想知道这种行为的理由是什么,就像在某些情况下为了防止传递无效类型而设置了方差限制一样。现在,我还了解到 C# 支持使用关键字“in”和“out”进行显式委托转换。像这样:
ExplicitFunction<Animal> processAnimal = Process<Animal>;
ExplicitFunction<Dog> processDog = processAnimal;
但是没有泛型我不能做同样的事情:
AnimalFunction processAnimalNonGeneric = AnimalProcess;
DogFunction processDogNonGeneric = processAnimalNonGeneric; // compile error
我有一种感觉,其原因可能与不支持隐式方差转换的原因密切相关。
问题2:但是为什么?为什么我不能像这样使用'in'关键字:
delegate void AnimalFunction(in Animal thing);
delegate void DogFunction(in Dog thing);
再一次,我知道这不是它的工作原理,但是排除此功能的理论上的“我们不能因为如果有人做了这个”的原因是什么?
}
PS 这段代码已经编译以确保它的行为与我描述的一样,并且只需要一个包装类和两个空Dog : Animal
类。