Scott DePouw
Scott DePouw

Reputation: 3899

Specify a C# Generic Constraint to be of ClassA OR ClassB?

Is there a way to specify that a generic type be of one type or another type?

public class SoftDrink<T>
    where T : TypeOne or TypeTwo
{ }

Upvotes: 9

Views: 427

Answers (6)

mlsteeves
mlsteeves

Reputation: 1271

You could always do a runtime check against the type:

class TypeOne
{
    int _integer = 0;
}

class TypeTwo
{
    int _integer = 3;
}

class TypeThree
{
}

class SoftDrink<T>
{
    public SoftDrink()
    {
        if (typeof(T) != typeof(TypeOne) && typeof(T) != typeof(TypeTwo))
        {
            throw (new Exception("Sorry, but T must be TypeOne or TypeTwo"));
        }
    }
}

//this works:
SoftDrink<TypeOne> t1 = new SoftDrink<TypeThree>();    

//throws an exception:
SoftDrink<TypeThree> t3 = new SoftDrink<TypeThree>();

Upvotes: 2

Khalid Abuhakmeh
Khalid Abuhakmeh

Reputation: 10839

You could have TypeOne and TypeTwo inherit an interface and then do the following.

 public class SoftDrink<T>
    where T: IMyType
    {}

Upvotes: 0

Sapph
Sapph

Reputation: 6208

Nope because that wouldn't make any sense. If you try to access a member function of "T", how can the compiler tell which base class to try and resolve members of?

You could try creating a common interface for TypeOne and TypeTwo and having the constraint specify that interface? What are you trying to accomplish, exactly?

Upvotes: 9

David M
David M

Reputation: 72930

You can't. The best you can do is use a common base class for the two, or a common interface implemented by both as a single type constraint.

Upvotes: 3

John Saunders
John Saunders

Reputation: 161831

You can extract the common functionality of TypeOne and TypeTwo into a base class or interface, and use that base class or interface as the constraint. Otherwise, how would the compiler know what it could do with T?

public interface IBelch
{
    void Belch();
}

public class Coke : IBelch
{
    public void Belch()
    {
    }
}

public class GatorAde : IBelch
{
    public void Belch()
    {
    }
}

public class SoftDrink<T>
    where T : IBelch
{
    public void DrinkFast(T drink)
    {
        drink.Belch();
    }
}

Upvotes: 2

user197015
user197015

Reputation:

No, however, you could constraint the class on a common base or interface.

In the CLR itself, the constraints (except for special ones, like the new-constraint) are stored rather simply: just a list of type identifiers, basically. So there's really no "room" for logical operations like you've specified... not without a revision to the CLR specification, or perhaps some really clever and ugly language-level tricks.

Upvotes: 2

Related Questions