我有以下课程
public class CalculatorManipulator<TCalculator>
where TCalculator : CachableCalculator
它包含字典:
protected Dictionary<string, TCalculator> Calculators { get; set; }
假设我尝试添加这样的项目
Calculators.Add(calc.CustomCaption, new CachableCalculator(calc, fg, cache));
为什么会产生这个编译时错误:
Argument type CachableCalculator is not assignable to parameter type TCalculator.
编译器知道TCalculator
是CachableCalculator
。
我想知道为什么我必须在它自动执行时进行投射。
这可以通过将其强制转换为TCalculator
来实现 Calculators.Add(calc.CustomCaption, (TCalculator)new CachableCalculator(calc, fg, cache));
答案 0 :(得分:5)
Dog
是Animal
;这并不意味着您可以假设任何Animal
都是Dog
,并将所有内容都扔进狗舍。
在此:TCalculator
是Dog
,CachableCalculator
是Animal
。可以将TCalculator
视为CachableCalculator
,但要反过来:您需要通过添加显式强制转换来告诉编译器您知道自己在做什么。
答案 1 :(得分:3)
为了更清楚,假设你有这个:
class Animal
{
}
class Dog : Animal
{
}
class AnimalManipulator<TAnimal> where TAnimal : Animal
{
readonly Dictionary<string, TAnimal> animals = new Dictionary<string, TAnimal>();
public void Test()
{
// Here you are forced to cast to the dictionary value type, because
// what you are doing is NOT SAFE:
animals.Add("Animal", (TAnimal)new Animal());
}
}
现在我们可以说明为什么上面的代码不安全:
var test = new AnimalManipulator<Dog>();
test.Test(); // Runtime exception.
在此示例中,TAnimal
的类型为Dog
,就通用约束TAnimal : Animal
而言,这是正常的。
但是,当您致电Test()
时,代码会尝试将Animal
投放到Dog
,这当然是不允许的。
就您的类型而言,您可以拥有一个派生自CachableCalculator
的类,并将其与CalculatorManipulator
一起使用,这将导致相同的异常。