C#泛型约束

时间:2010-03-06 09:11:06

标签: c# generics constraints

是否可以枚举通用约束中哪些类型“可用”?

T MyMethod<t>() where T : int, double, string

为什么我要这样做是因为我有一个小的评估引擎并且想要 写这样的代码:

bool expression.Evaluate<bool>();

int expression.Evaluate<int>();

但我想禁止

MyCustomClass expression.Evalaute<MyCustomClass>();

3 个答案:

答案 0 :(得分:10)

如果泛型类型参数的可能性很小,那么该方法不是真正的泛型。泛型的要点是允许对类型和方法进行参数化,以便您可以根据需要创建无限多个不同的类型和方法。如果您只有三种可能的类型,那么请编写三种方法。也就是说,创建重载,不要使用泛型。

答案 1 :(得分:6)

无法将通用参数限制为特定类型。

作为一种变通方法,您可以为每种类型提供一种方法,并将方法调用转发到一个通用实现:

public class Expression {

    public bool EvaluateToBool() {
        return Evaluate<bool>();
    }

    public int EvaluateToInt32() {
        return Evaluate<int>();
    }

    private T Evaluate<T>() {
        return default(T);
    }
}

另一方面,您是否考虑过在Expression类型中对表达式求值的类型进行编码? 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();
    }
}

答案 2 :(得分:1)

不,你不能。

您可以添加以下通用约束:

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添加编译时限制。