我有一个泛型方法,它使用泛型参数作为字典的键:
<div className={this.rootClassNames()}></div>
此代码效果很好。但是,当然,如果你这样称呼它:
public void MyMethod<T>(IEnumerable<T> myCollection) where T : IMyInterface
{
var smthg = MyDictionary[typeof(T)];
//...
}
MyMethod(myCollectionOfT.Cast<IMyInterface>());
将是T
(不是实现IMyInterface
的类),字典将没有密钥(这是正常的)。
出现问题时,我很容易抛出异常:
IMyInterface
但是当你的调用使用接口而不是实现它的类时,是否有一种方法(约束或其他)产生编译时错误?
编辑:
D Stanley 提供了一个解决方案:if (typeof(T) == typeof(IMyInterface)) throw new ArgumentException("The generic parameter should be strongly typed.", "T");
约束会保证new()
不是界面。
答案 0 :(得分:0)
如果您正在处理引用类型,则可以使用编辑:实际上,它也匹配“仅”接口。哦,好吧。class
约束。
这更像是一个设计问题 - 你在功能上非虚拟的方式使用接口(在更广泛的意义上)。怎么办
MyMethod(MyListOfDerivedClass.Cast<MyBaseClass>())
由于您违反了接口和继承的设计,因此必须确保您自己的规则不会被破坏。您不能依赖编译器或通常的OOP设计规则,因为您违反了这些规则。
通过将通用方法设计为接受IEnumerable<IMyInterface>
类型的任何参数,您可以说IMyInterface
的任何实现都应该有效。同样地,只要它们都正确地实现IMyInterface
,枚举中的项目是否具有不同类型并不重要。任何方法都是一样的,无论它是否通用。你正在做的事情类似于拥有一个接受Control
的方法,但只有在你实际传递Label
或Button
时才会有效,并且在其他任何事情上失败,包括类型派生来自Label
或Button
。
答案 1 :(得分:-1)
您可以使用类似此代码的内容
public void MyMethod<T>(IEnumerable<T> myCollection) where T : IMyInterface, class, new()
{
var smthg = MyDictionary[typeof(T)];
//...
}
根据MSDN Constraints on Type Parameters 修改强> class意味着T必须是引用类型;这也适用于任何类,接口,委托或数组类型。所以如果构造函数是公共的,你可以使用new()来检查T是否为class。