It is not possible to restrict a generic argument to specific types.
As a workaround, you could provide plain old overloads and forward the method calls to a common implementation:
public class Expression {
public bool Evaluate() {
return Evaluate<bool>();
}
public int Evaluate() {
return Evaluate<int>();
}
private T Evaluate<T>() {
return default(T);
}
}
On the other hand, have you thought about encoding the type the expression evaluates to in the Expression type? E.g.
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();
}
}