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).
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.
You can use the
EDIT: Actually, that matches "just" interfaces as well. Oh well. class
constraint if you're dealing with reference types.
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.
By designing your generic method to accept any argument of type IEnumerable<IMyInterface>
, you're saying that any implementation of IMyInterface
should be valid. 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. 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
.
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; 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.