基本的に、C# ではテンプレートの特殊化は許可されませんが、次のような継承による場合を除きます。
interface IFoo<T> { }
class Bar { }
class FooBar : IFoo<Bar> { }
少なくとも、コンパイル時にはこれをサポートしていません。ただし、RTTI を使用して、達成しようとしていることを行うことができます。
public bool Save<T>(T entity)
{
// Check if "entity" is of type "SpecificClass"
if (entity is SpecificClass)
{
// Entity can be safely casted to "SpecificClass"
return SaveSpecificClass((SpecificClass)entity);
}
// ... other cases ...
}
このis
式は、実行時の型チェックを行うのに非常に便利です。次のコードと同様に機能します。
if (entity.GetType() == typeof(SpecificClass))
// ...
編集: 未知の型が次のパターンを使用するのはかなり一般的です:
if (entity is Foo)
return DoSomethingWithFoo((Foo)entity);
else if (entity is Bar)
return DoSomethingWithBar((Bar)entity);
else
throw new NotSupportedException(
String.Format("\"{0}\" is not a supported type for this method.", entity.GetType()));
EDIT 2:他の回答がメソッドをオーバーロードSpecializedClass
することを示唆しているように、ポリモーフィズムを使用している場合は注意が必要です。リポジトリにインターフェイスを使用している場合 (これは、実際にはリポジトリ パターンを設計するための良い方法です)、オーバーロードによって間違ったメソッド get が呼び出される場合がありますSpecializedClass
。インターフェース:
interface IRepository
{
bool Save<T>(T entity)
where T : class;
}
class FooRepository : IRepository
{
bool Save<T>(T entity)
{
}
bool Save(Foo entity)
{
}
}
これは、次FooRepository.Save
のインスタンスで直接呼び出すと機能しますFoo
。
var repository = new FooRepository();
repository.Save(new Foo());
ただし、インターフェイスを呼び出している場合 (たとえば、パターンを使用してリポジトリ作成を実装している場合)、これは機能しません。
IRepository repository = GetRepository<FooRepository>();
repository.Save(new Foo()); // Attention! Call's FooRepository.Save<Foo>(Foo entity) instead of FooRepository.Save(Foo entity)!
RTTI を使用する方法は 1 つしかなくSave
、問題ありません。