2016-07-31 4 views
0

次のスニペットのいずれもコンパイルされない理由を頭に入れて問題を解決しています。`this`をジェネリック型にキャストできないのはなぜですか?

Visual Studioのフラグを持つ最初の1:

は 'T'

キャストに型 'SomeType' を変換できませんが冗長です。 "冗長" のキャストを削除

using System; 

public class SomeClass { 
    public T Coerce<T>() { 
     if (typeof(T) == typeof(SomeClass)) 
      return (T)this; // <- Error CS0030 
     else throw new InvalidCastException(); 
    } 
} 

は、しかし、ちょうどにエラーを変更します。

が暗黙的にタイプを変換できません 'SomeOtherClass' 'T'

using System; 

public class SomeOtherClass { 
    public T Coerce<T>() { 
     if (typeof(T) == typeof(SomeOtherClass)) 
      return this; // <- Error CS0029 
     else throw new InvalidCastException(); 
    } 
} 
+0

ここで*達成しようとしていることを説明したなら、おそらく助けになるでしょう。 –

+2

'return(T)(オブジェクト)this;' – PetSerAl

+1

なぜあなたはこれをしたいですか? –

答えて

2

へコンパイラは何が間違っているかを正確に伝えています:SomeClassTに暗黙的に変換することはできませんが、実際にはあなたが注意を払う必要がある2つのこと。

最初に、コンパイル時に型がわからないため、暗黙的に汎用型に変換できないことがあります。明示的にキャストするか、暗黙の変換が本当に必要な場合は継承を使用する必要があります。

もう1つは、値型と参照型を区別するために(制約を介して)もう少し型情報が必要であることです。現在、コンパイラはを何も持っていません。Tです。 classは決してキャストできないintでもかまいません。

あなたがclass制約を必要とし、それだけで正常に動作しますTに参照型をキャストするために:

public class SomeClass 
{ 
    public T Coerce<T>() where T : class 
    { 
     if (typeof(T) == typeof(SomeClass)) 
      return this as T; 
     else throw new InvalidCastException(); 
    } 
} 

を今コンパイラもsomeClassInstance.Coerce<int>()のようなものをやってからあなたを防ぐことができますし、それがポイントです。

EDIT(T)(object)thisの例として

あなたはもはやTthisをキャストしているため、これが働きません。代わりにthisobjectにキャストします(これは、すべてのの他のタイプが派生しているためです)、同じ理由で動作するobjectからTにキャストします。あなたはコンパイル時のチェックを迂回しています。

これを実行してsomeClassInstance.Coerce<int>()を呼び出すと、「指定されたキャストは無効です」という例外が表示されます。 ランタイム。ただし、一般的な制約を使用すると、コンパイル時にという警告が表示されます()。

それでも問題がなければ、return (dynamic)this;はもっと簡単な解決策です。しかし、それはジェネリック薬を使う目的を打ち消すものです。

+0

しかし、なぜ 'return(T)(object)this;'制約なしで動作するのですか? –

+1

これはコンパイラを騙す単なる方法であり、 'dynamic'を使うこととかなり密接に関連しています(正しい型にキャストしなければ厄介なランタイムエラーが発生します)。オブジェクトは何でもかまいません:値型または参照型(この理由でジェネリック制約として 'object'を使用することはできません) –

+0

これらの異なるアプローチの意味に固有のもう少し説明で私の答えを更新しました –

関連する問題