Generic method multiple (OR) type constraint

Botz answer is 100% correct, here's a short explanation:

When you are writing a method (generic or not) and declaring the types of the parameters that the method takes you are defining a contract:

If you give me an object that knows how to do the set of things that Type T knows how to do I can deliver either 'a': a return value of the type I declare, or 'b': some sort of behavior that uses that type.

If you try and give it more than one type at a time (by having an or) or try to get it to return a value that might be more than one type that contract gets fuzzy:

If you give me an object that knows how to jump rope or knows how to calculate pi to the 15th digit I'll return either an object that can go fishing or maybe mix concrete.

The problem is that when you get into the method you have no idea if they've given you an IJumpRope or a PiFactory. Furthermore, when you go ahead and use the method (assuming that you've gotten it to magically compile) you're not really sure if you have a Fisher or an AbstractConcreteMixer. Basically it makes the whole thing way more confusing.

The solution to your problem is one of two possiblities:

  1. Define more than one method that defines each possible transformation, behavior, or whatever. That's Botz's answer. In the programming world this is referred to as Overloading the method.

  2. Define a base class or interface that knows how to do all the things that you need for the method and have one method take just that type. This may involve wrapping up a string and Exception in a small class to define how you plan on mapping them to the implementation, but then everything is super clear and easy to read. I could come, four years from now and read your code and easily understand what's going on.

Which you choose depends on how complicated choice 1 and 2 would be and how extensible it needs to be.

So for your specific situation I'm going to imagine you're just pulling out a message or something from the exception:

public interface IHasMessage
{
    string GetMessage();
}

public void test(string a, IHasMessage arg)
{
    //Use message
}

Now all you need are methods that transform a string and an Exception to an IHasMessage. Very easy.


That is not possible. You can, however, define overloads for specific types:

public void test(string a, string arg);
public void test(string a, Exception arg);

If those are part of a generic class, they will be preferred over the generic version of the method.