基本上,除了通过继承这种方式之外,C# 并不允许模板特化,如下所示:
interface IFoo<T> { }
class Bar { }
class FooBar : IFoo<Bar> { }
至少在编译时不支持此功能。但是,您可以使用RTTI来实现您想要的功能:
public bool Save<T>(T entity)
{
if (entity is SpecificClass)
{
return SaveSpecificClass((SpecificClass)entity);
}
}
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()));
编辑2: 正如其他答案建议的那样,使用
SpecializedClass
重载方法时,如果您正在使用多态性,则需要注意。如果您正在为存储库使用接口(实际上这是设计存储库模式的好方法),则存在一些情况,重载可能导致调用错误的方法,无论您是否将
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),只需一个“Save”方法,您就可以顺利完成。