2016-06-13 5 views
1

が、私は次のクラスに引数の型Xは、Xが句

public class CalculatorManipulator<TCalculator> 
     where TCalculator : CachableCalculator 

を持って、それは辞書が含まれている場所として指定されたジェネリック型Tに割り当てられませんそう

Calculators.Add(calc.CustomCaption, new CachableCalculator(calc, fg, cache)); 

のような項目は、なぜ、この収率は、今回のエラーをコンパイルん:

Argument type CachableCalculator is not assignable to parameter type TCalculator. 

コンパイラは、TCalculatorCachableCalculatorであることを認識しています。

私はなぜそれを自動的に行うことができるのですか?

これはDogAnimalあるTCalculator

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

答えて

5

にそれをキャストすることによって動作します。それはあなたがAnimalDogであると仮定でき、すべてを犬小屋に投げることを意味することを意味するものではありません。

この中でTCalculatorDogであり、CachableCalculatorAnimalである。 TCalculatorCachableCalculatorとして扱ってもかまいませんが、それを逆に行うことができます。明示的なキャストを追加して、実行中のことをコンパイラーに伝える必要があります。

+0

しかし、私たちは犬を追加しています。< – Hristo

+1

@Chrisあなたはそれを知っています。コンパイラはしません。実際、あなたのコードは有効ではないと思います。辞書は 'Dictionary 'ですが、あなたは** Dog ** - 新しいCachableCalculator(...)ではなく** Animal **を明示的に**追加しています。 'は' TCalculator'ではありません**。これは 'CachableCalculator'です。あなたのコードは** CalculatorManipulator のために**実際にしか**働いています –

+0

@MarcGravellは彼のコメントで正しいです、コードはキャストでコンパイルしますが、実行時にクラッシュします。 –

2

この明確には、あなたがこれを持っていることを前提とし作成するには:

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()を呼び出すと、コードはAnimalDogにキャストしようとしますが、これはもちろん許可されていません。

あなたのタイプに関しては、CachableCalculatorから派生したクラスを持つことができ、CalculatorManipulatorでそれを使用すると、同等の例外が発生します。

+0

ええ、それは今私にとって理にかなっています。 – Hristo

関連する問題