-2

To illustrate it with an example:

    ??? public class Foo<T> where T:(ClassA || ClassB){}

Is it possible to restrict T for a number of unrelated classes in an or relationship (T is either ClassA or ClassB, but nothing else) or the only way to achieve this is to either

  • make ClassA and ClassB both implement the same interface
  • have both classes derive from the same base class

and use these as constraints?

So, to make things clear: my question does not concern whether you can have n number of generic constraints for n number of variables, I want to know if I can have n number of constraints for the very same variable.

6
  • There is no OR, all you can do is make a constraint to a base class or interface Commented Feb 10, 2018 at 13:19
  • 3
    Suppose it was possible, how would you work with ClassA.Foo that is not in ClassB? What when members have the same name but different types? Commented Feb 10, 2018 at 13:21
  • @Mark Benningfield: That question is about constraining two different type parameters. This one's about applying two constraints to one type parameter. Commented Feb 10, 2018 at 13:21
  • See answer to this question @BoltClock: I've withdrawn the flag, but I knew I'd seen this addressed before. Commented Feb 10, 2018 at 13:24
  • @HenkHolterman: My question is rather theoretical in nature, although I can imagine something like: my class can work with these two unrelated classes that return the same result. I would implement a different type of logic for both and return the appropriate. This, of course, can be done using interfaces. Commented Feb 10, 2018 at 13:31

4 Answers 4

3

I would implement a different type of logic for both and return the appropriate. This, of course, can be done using interfaces.

Even if you can promise that both types have the exact same members, the compiler has no way of verifying this.

By having both classes implement the same interface, you make that guarantee to the compiler that they do share at least the members of the interface, and those members are available to the generic class to use. This is the reason interfaces exist as well as the whole point of generics.

Sign up to request clarification or add additional context in comments.

Comments

2

No, and if you think about it, it wouldn't be very useful.

The purpose of applying generic constraints is to ensure that the code is able to do certain operations on the type. E.g. the new() constraint ensure you can do new T(), which is not possible for an unconstrained type. But applying an "or" constraint does not provide any useful static guarantees for T, so you cant really use it for anything.

You can have multiple constraints for a single type variable though, but they are "and" constraints, i.e. they all have to be fulfilled.

1 Comment

I know, I just asked out of curiosity :)
1

If I get it right, you basically want to evaluate an expression as part of the constraint and to my best knowledge it isn't possible.

Type parameters can have multiple constraints though, just not as an expression. See here from this example:

class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new()
{
    // ...
}

Here T sure has multiple constraints, but not as an expression.

In this case though you might wish to take a look at your design to eliminate the need of your question.

Comments

0

Short answer is: No, you can't. Others already explained why, but in short you would lose the type safety that comes with generics.

If for whatever reason you still needs this, there is a solution to use method overloads and the compiler does the rest.

public void Foo<T>(T instance) where T : ClassA
{
   GenericFoo(instance);
}

public void Foo<T>(T instance) where T : ClassB
{
    GenericFoo(instance);
}

private void GenericFoo(object instance)
{
  // Do stuff
}

6 Comments

Why would you suggest a compile-time type-safe method to call an object overload? Just remove those generics completely
Because the object one is private and now I can guarantee the object is either ClassA or ClassB as the OP asked for. I would not do any of this, I just answered the question.
"use method overloads and the compiler does the rest" The compiler doesn't really get to do anything here except compile the code...
It does select the correct signature of the method based on type constraint so that in code Foo(new ClassA()) and Foo(new ClassB()) work, but Foo(new ClassC()) will not compile which is exactly what OP asked for.
Note that in the question Foo<T> is a class, not a method, so this does have the caveat of moving the generic from class to method.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.