Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constraints taking either types in generics

Tags:

c#

In generics we can give constraints using the "where" clause like

public void MyGeneric <T>() where T : MyClass1 {...}

Now if i want the type T to be of type MyClass1 and say an interface IMyInterface then i need to do something like

public void MyGeneric <T>() where T : MyClass1, IMyInterface  {...}

But I dont know (or maybe it is not possible) if we can create a generic method that can take types which inherits from either of the 2 types. i.e. if any of my other classes inherits from MyClass1 or implements IMyInterface but neither of my class has both then my generic method should work for these classes.

I hope I have been clear.

like image 430
samar Avatar asked Aug 11 '10 13:08

samar


2 Answers

You can't, and for a good reason. Say MyClass1 and IMyInterface both have a CoolThing() method (presumably such commonality is precisely why you want to do this sort of thing in the first place). You sort of want code like:

public void MyGeneric<T>(T item) where T : MyClass1 or T : IMyInterface
{
  item.CoolThing();
}

The problem with this is that as MyClass1.CoolThing() is defined completely differently to IMyInterface.CoolThing(). You may know that they do essentially the same thing, but they may be very different indeed (Employee.Fire() is presumably very different to Gun.Fire() and so on).

You've got two options that I can see. One is to define two different methods. Overloading will reduce the headache of calling them, and they could share some pieces of their implementation in a private method that doesn't depend upon the relevant features of the MyClass1 and IMyInterface signatures.

The other is to use reflection to obtain the MethodInfo of the method called "CoolThing" on the object in question, and then invoke it. This latter obviously blows away your compile time type safety.

like image 127
Jon Hanna Avatar answered Sep 22 '22 23:09

Jon Hanna


As anyone before says you cannot ceate or-constraints, but there is the clear and simple way to bypass this problem.

Put some extra interface on all the classes and interfaces that you want to be valid types for a generic arguments. Thats the solution that will let you to use them all in generic methods without leting any other to be used.

For example:

class MyClass1 : IAllowInMyGeneric { ... }
interface IMyInterface : IAllowInMyGeneric { ... }

public void MyGeneric <T>() where T : IAllowInMyGeneric {...}
like image 27
Łukasz W. Avatar answered Sep 19 '22 23:09

Łukasz W.