简体   繁体   English

确保通用参数是具体类型

[英]Ensure generic parameter is a concrete type

I have a generic method that uses the generic parameter as the key of a dictionary: 我有一个通用方法,使用通用参数作为字典的键:

public void MyMethod<T>(IEnumerable<T> myCollection) where T : IMyInterface
{
    var smthg = MyDictionary[typeof(T)];
    //...
}

This code works well. 此代码运行良好。 But of course, if you call it like that: 但是,当然,如果您这样称呼它:

MyMethod(myCollectionOfT.Cast<IMyInterface>());

T will be IMyInterface (not a class that implements IMyInterface ), and the dictionary won't have the key (which is normal). T将是IMyInterface (不是实现IMyInterface的类),并且字典将没有键(这是正常的)。

I can easily have an exception thrown when the problem occurs: 问题发生时,我很容易引发异常:

if (typeof(T) == typeof(IMyInterface)) throw new ArgumentException("The generic parameter should be strongly typed.", "T");

But is there a way (constraint or something) to have a compile-time error when your call uses the interface instead of a class that implements it? 但是,当您的调用使用该接口而不是实现该接口的类时,是否有办法(约束等)发生编译时错误?

Edit: 编辑:

D Stanley gave a solution: the new() constraint would garantee that T is not an interface. D Stanley提供了一个解决方案: new()约束将确保T不是接口。

You can use the class constraint if you're dealing with reference types. 如果要处理引用类型,则可以使用 class约束。 EDIT: Actually, that matches "just" interfaces as well. 编辑:实际上,这也匹配“只是”接口。 Oh well. 那好吧。

It's really more of a design problem - you're using interfaces (in broader sense) in a functionally non-virtual way. 实际上,这实际上是一个设计问题-您正在以一种功能非虚拟的方式使用接口(广义上来说)。 What if I do 如果我该怎么办

MyMethod(MyListOfDerivedClass.Cast<MyBaseClass>())

?

Since you're violating the design of interfaces and inheritance, you must ensure that your own rules aren't broken. 由于您违反了接口和继承的设计,因此必须确保自己的规则不被破坏。 You can't rely on the compiler or the usual OOP design rules, since you're violating those. 您不能依赖编译器或通常的OOP设计规则,因为您违反了这些规则。

By designing your generic method to accept any argument of type IEnumerable<IMyInterface> , you're saying that any implementation of IMyInterface should be valid. 通过设计通用方法以接受任何类型为IEnumerable<IMyInterface> ,您就是说IMyInterface任何实现都应该有效。 The same way, it doesn't matter if the items in the enumerable are of different types as long as they all implement IMyInterface properly. 以同样的方式,可枚举中的项目是否为不同类型都没关系,只要它们都正确实现了IMyInterface It's the same thing with any method, regardless of whether it's generic or not. 任何方法都一样,无论它是否通用。 What you're doing is akin to having a method that accepts Control , but only works when you actually pass Label or Button , and fails for anything else, including types derived from Label or Button . 您正在执行的操作类似于具有接受Control的方法,但仅在您实际传递LabelButton ,而对其他所有操作(包括从LabelButton 派生的类型)都无效。

You can use something like this code 您可以使用类似下面的代码

public void MyMethod<T>(IEnumerable<T> myCollection) where T : IMyInterface, class, new()
{
    var smthg = MyDictionary[typeof(T)];
    //...
}

according to MSDN Constraints on Type Parameters Edit: class means that T must be a reference type; 根据MSDN对类型参数的约束 Edit: class表示T必须是引用类型; this applies also to any class, interface, delegate, or array type. 这也适用于任何类,接口,委托或数组类型。 so you can use new() to check that T is class if your constructor is public. 因此,如果您的构造函数是公共的,则可以使用new()来检查T是否为类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM