以下の例(デモ目的のみ)では、T
がクラスに制約されていない場合、この変換は次のようになります。
var ret = objectA as T;
..次のコンパイルエラーが発生します:
型パラメーター「T」は、クラス型制約も「クラス」制約もないため、「as」演算子と一緒に使用することはできません。
なぜこれができないのか理解できません。 T
をインターフェイスIObject
に制約したので、コンパイラはT
がインターフェイスタイプであり、as
操作が有効であることを認識している必要があります。
public interface IObject
{
string Id { get; set; }
}
public class ObjectA : IObject
{
public string Id { get; set; }
}
public class ObjectFactory
{
public T CreateObject<T>(string id) where T : IObject
{
ObjectA objectA = new ObjectA();
var x = objectA as IObject; // this is good
var ret = objectA as T; // why this 'as' cannot compile?
return ret;
}
public T CreateClassObject<T>(string id) where T : class, IObject
{
ObjectA objectA = new ObjectA();
var ret = objectA as T; // if T is class, this 'as' can compile
return ret;
}
}
tをインターフェイスIObjectに制限したので、コンパイラはTがインターフェイスタイプである必要があり、「as」操作が有効である必要があることを認識している必要があります。
いいえ、T
はインターフェースタイプである必要はありません。 インターフェースを実装するタイプである必要があります。考えてみましょう:
_public struct Foo : IObject
{
public string Id { get; set; }
}
_
では、CreateObject<Foo>("ff")
に何を期待しますか?
class
にCreateObject
制約がある場合、Foo
は参照型ではないため、その呼び出しは無効になります-コンパイラはT
が参照型なので、_objectA as T
_は問題ありません。