参数类型X不能分配给泛型类型T,其中X被指定为where子句

时间:2016-06-13 08:01:07

标签: c# .net

我有以下课程

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.

编译器知道TCalculatorCachableCalculator

我想知道为什么我必须在它自动执行时进行投射。

这可以通过将其强制转换为TCalculator

来实现
     Calculators.Add(calc.CustomCaption, (TCalculator)new CachableCalculator(calc, fg, cache));

2 个答案:

答案 0 :(得分:5)

DogAnimal;这并不意味着您可以假设任何Animal都是Dog,并将所有内容都扔进狗舍。

在此:TCalculatorDogCachableCalculatorAnimal。可以将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一起使用,这将导致相同的异常。