C#泛型约束

13
这句话的意思是:在泛型约束中,是否可以列举出“可用”的类型?
T MyMethod<t>() where T : int, double, string

我想这样做的原因是我有一个小型的评估引擎,希望能够编写类似这样的代码:
bool expression.Evaluate<bool>();

或者

int expression.Evaluate<int>();

但我想禁止。
MyCustomClass expression.Evalaute<MyCustomClass>();

请看这个问题:https://dev59.com/gXVD5IYBdhLWcg3wRpeX - M4N
1
你确定 Evaluate<bool>()Evaluate<int>() 有相同的实现吗?如果你的方法只适用于特定类型列表,那么很可能你的方法并不像你想象的那样通用。 - dtb
2
@dtb:感谢你的提示,我想那就是我的真正问题,我想我的懒惰正在控制我,只想写一个方法 :) - Marcus
3个回答

11
如果泛型类型参数的可能性很小,那么该方法就不是真正的“通用”。泛型的目的是允许对类型和方法进行参数化,以便您可以按需创建无限种不同的此类类型和方法。如果只有三种可能的类型,则编写三种方法。也就是说,创建重载,而不是使用泛型。

2
不易维护。如果“通用”不是正确的术语,则使用正确的术语构建不同的结构。 - user652038
即使可能性有限,对于应用程序的“中间”层来说,使用泛型有时也是有利的。例如,假设一个人希望编写一个例程来对数组中的数字执行某些算法,并且该算法仅取决于能够比较两个元素或取两个元素的和。如果有一个静态方法 T ComputeSum <T>(T x,T Y),它适用于任何数值原始类型,则使用泛型将使得单个源代码方法能够在任何受支持的类型上执行算法成为可能。 - supercat

6

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

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

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();
    }
}

再次感谢,这甚至比我想到的解决方案更好。 - Marcus
4
你的第一个代码示例无效。你不能仅凭返回类型来重载函数。 - dthorpe

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和字符串添加编译时约束。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接