Невозможно ограничить общий аргумент определенными типами.
В качестве обходного пути вы могли бы предоставить метод для каждого типа и перенаправить вызовы методов в общую реализацию:
public class Expression {
public bool EvaluateToBool() {
return Evaluate<bool>();
}
public int EvaluateToInt32() {
return Evaluate<int>();
}
private T Evaluate<T>() {
return default(T);
}
}
С другой стороны, думали ли вы о кодировании типа, который вычисляется выражением, в типе выражения? Например.
public abstract class Expression<T> {
public abstract T Evaluate();
}
public sealed class AddExpression : Expression<int> {
public AddExpression(Expression<int> left, Expression<int> right) {
this.Left = left;
this.Right = right;
}
public Expression<int> Left { get; private set; }
public Expression<int> Right { get; private set; }
public override int Evaluate() {
return this.Left.Evaluate() + this.Right.Evaluate();
}
}
Нет, не можете.
Вы можете добавить следующее общее ограничение:
T MyMethod<T>() where T : struct {}
А затем:
bool expression.MyMethod<bool>(); //OK
int expression.MyMethod<int>(); //OK
string expression.MyMethod<string>(); //fails! string is a reference type
struct MyStruct {}
MyStruct MyMethod<MyStruct>(); //OK! MyStruct is a value type
class MyCustomClass {}
MyCustomClass MyMethod<MyCustomClass>(); //FAILS! MyCustomClass is a reference type
Но вы не можете добавить ограничения времени компиляции для int и string одновременно.
Если у вас есть небольшое количество возможностей для аргумента типа generic, то метод не является действительно generic. Смысл дженериков в том, чтобы позволить параметризацию типов и методов, чтобы вы могли создавать бесконечно много различных таких типов и методов по требованию. Если у вас есть только три возможных типа, напишите три метода. То есть, создавайте перегрузки, не используйте дженерики.