【问题标题】:C# generic constraints [duplicate]C#通用约束[重复]
【发布时间】:2011-01-24 10:04:05
【问题描述】:

是否可以枚举泛型约束中“可用”的类型?

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

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

bool expression.Evaluate<bool>();

int expression.Evaluate<int>();

但我想禁止

MyCustomClass expression.Evalaute<MyCustomClass>();

【问题讨论】:

  • 您确定Evaluate&lt;bool&gt;()Evaluate&lt;int&gt;() 具有相同的实现吗?如果您的方法仅适用于特定类型列表,那么您的方法可能不像您想象的那样通用。
  • @dtb:谢谢你的提示,我认为那是我真正的问题,我想懒惰正在抓住我,只想写一个方法。 :)

标签: c# generics constraints


【解决方案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 添加编译时间限制。

【讨论】:

    【解决方案2】:

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

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

    public class Expression {
    
        public bool EvaluateToBool() {
            return Evaluate<bool>();
        }
    
        public int EvaluateToInt32() {
            return Evaluate<int>();
        }
    
        private T Evaluate<T>() {
            return default(T);
        }
    }
    

    另一方面,您是否考虑过在 Expression 类型中对表达式求值的类型进行编码?例如

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

    【讨论】:

    • 再次感谢,这是比我想象的更好的解决方案。
    • 您的第一个代码示例无效。您不能仅通过返回类型重载函数。
    【解决方案3】:

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

    【讨论】:

    • 不可维护。如果“通用”不是正确的术语,请使用正确的术语构建不同的结构。
    • 即使存在离散数量的可能性,使用泛型有时也可能对应用程序的“中间”层有利。例如,假设一个人希望编写一个例程来对数组中的数字执行某种算法,并且该算法仅取决于能够比较两个元素或获取两个元素的总和。如果有一个静态方法T ComputeSum&lt;T&gt;(T x, T Y) 可用于任何数字基元类型,那么使用泛型将使源代码中的单个方法可以在任何支持的类型上执行算法。
    猜你喜欢
    • 1970-01-01
    • 2013-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-08
    • 2011-03-20
    相关资源
    最近更新 更多