简体   繁体   English

在C#5.0中改进了泛型类型的功能/运算符重载吗?

[英]Has generic type's features/operator overloading improved in C# 5.0?

I know there are many question on SO like this 我知道有很多关于这样的问题
"Operator 'whatever' cannot be applied to operands of type 'T' (whatever may be ++, += or <= etc. etc. But bear with me, I wanna ask something different. "Operator 'whatever' cannot be applied to operands of type 'T' (无论是++,+ =或<=等等。但请耐心等待,我想问一些不同的东西。

Let's say I have this code 假设我有这个代码

public class GenericCls<T> where T : struct
{
    public static T AddValues(params T[] values)
    {
        T sum = default(T);
        if (values != null)
        {
            for (int i = 0; i < values.Length; i++)
            {
                sum += values[i];
            }
        }
        return sum;
    }
}

even though I've made my type struct, and value type I get the error Operator '+=' cannot be applied to operands of type 'T' and 'T' 即使我已经创建了我的类型结构,并且值类型I得到错误Operator '+=' cannot be applied to operands of type 'T' and 'T'

If I try to be subtle and apply the ValueType constraint, it says Constraint cannot be special class 'System.ValueType' 如果我尝试细微并应用ValueType约束,则表示Constraint cannot be special class 'System.ValueType'

If I try to turn the parameter in for loop to type T, and do this.. 如果我尝试将for循环中的参数转换为T型,并执行此操作..

public class GenericCls<T> where T : struct, IComparable<T>, IEquatable<T>
{
    public static T AddValues(params T[] values)
    {
        T sum = default(T);
        if (values != null)
        {
            for (T i = default(T); i < values.Length; i++)
            {
                sum += values[i];
            }
        }
        return sum;
    }
}

I still get errors 我仍然得到错误

Operator '<' cannot be applied to operands of type 'T' and 'int'
Operator '++' cannot be applied to operand of type 'T'
Cannot implicitly convert type 'T' to 'int'

No matter what, I can't get it to work. 无论如何,我都无法让它发挥作用。 I am using VS2010 (C# 4.0, .NET 4.0). 我使用的是VS2010(C#4.0,.NET 4.0)。 So I wanna know when C# 5.0 would be finally released with VS2012 (as far as I know they are still in beta stage right?) would it take care of these issues? 所以我想知道什么时候C#5.0最终会与VS2012一起发布(据我所知他们仍然处于测试阶段?)它会处理这些问题吗? Or are we again left with so many restriction on usage of Generics? 或者我们是否再次对泛型的使用有如此多的限制?

It is possible without language improvements, but you have to use some tricks and cannot apply it to existing numeric types, but have to create new ones. 没有语言改进是可能的,但你必须使用一些技巧,不能将它应用于现有的数字类型,但必须创建新的。 One of them is the curiously recurring pattern class C<T> : where T : C<T> . 其中之一是奇怪的重复模式class C<T> : where T : C<T> Another trick is to use static delegates for the operations. 另一个技巧是使用静态委托进行操作。 I define a numeric class like this (for the sake of simplicity I only define the addition): 我定义了一个这样的数字类(为了简单起见,我只定义了添加):

public abstract class Numeric<T>
    where T : Numeric<T>
{
    public static Func<T, T, T> Add;

    public static T operator +(Numeric<T> x, Numeric<T> y)
    {
        if (x == null) {
            return (T)y;
        }
        if (y == null) {
            return (T)x;
        }
        return Add((T)x, (T)y);
    }
}

Note that we have to specify at least one type as Numeric<T> when overloading the operator (one type must always be the class that overloads the operator). 请注意,在重载运算符时,我们必须至少指定一个类型为Numeric<T> (一种类型必须始终是重载运算符的类)。 Note also that we can cast Numeric<T> to T because of the generic constraint where T : Numeric<T> 另请注意,由于where T : Numeric<T>的通用约束,我们可以将Numeric<T>T

Now we can declare a calculator like this. 现在我们可以声明这样的计算器。 Since Numeric<T> overloads the + operator, we can use += here. 由于Numeric<T>重载了+运算符,我们可以使用+= here。

public class Calculator<T> where T : Numeric<T>
{
    public static T AddValues(params T[] values)
    {
        T sum = default(T);
        if (values != null) {
            for (int i = 0; i < values.Length; i++) {
                sum += values[i];
            }
        }
        return sum;
    }
}

Now lets define a concrete Numeric class. 现在让我们定义一个具体的Numeric类。 In the static constructor we define the static Add delegate. 在静态构造函数中,我们定义静态Add委托。 Since the operators are static, this delegate must be static as well because it is called from within the operator method, and since static members cannot be virtual, we must use this delegate-trick. 由于运算符是静态的,因此该委托也必须是静态的,因为它是在operator方法中调用的,并且由于静态成员不能是虚拟的,所以我们必须使用这个委托技巧。

public class Complex : Numeric<Complex>
{
    static Complex()
    {
        Add = (x, y) => new Complex(x.Re + y.Re, x.Im + y.Im);
    }

    public double Re { get; private set; }
    public double Im { get; private set; }

    public Complex(double re, double im)
    {
        Re = re;
        Im = im;
    }

    public override string ToString()
    {
        return String.Format("({0}, {1})", Re, Im);
    }
}

Now lets test this tricky construction 现在让我们来测试这个棘手的构造

static class Test
{
    public static void AddComplexNumbers()
    {
        // Using the calculator
        var numbers = new Complex[] { new Complex(2, 7), new Complex(6, -2) };
        var result = Calculator<Complex>.AddValues(numbers);
        Console.WriteLine(result); // ==> (8, 5)

        // Directly
        var c1 = new Complex(2, 7);
        var c2 = new Complex(6, -2);
        result = c1 + c2;
        Console.WriteLine(result); // ==> (8, 5)

    }
}

No, it will not improve this issue. 不,它不会改善这个问题。 C#5 will offer async-await and a few minor features. C#5将提供async-await和一些次要功能。 But not an extended version of generics that works with method/operator overloading. 但不是与方法/运算符重载一起使用的泛型的扩展版本。

For comparisons you can use IComparer<T> and IComparable<T> as a workaround, but for arithmetic there is no good solution. 对于比较,您可以使用IComparer<T>IComparable<T>作为解决方法,但对于算术,没有好的解决方案。 There are a few techniques, but they either make the API ugly, or they're slow. 有一些技术,但它们要么使API丑陋,要么它们很慢。


If I try to be subtle and apply the ValueType constraint, it says "Constraint cannot be special class System.ValueType " 如果我试图微妙并应用ValueType约束,它说“约束不能是特殊类System.ValueType

The equivalent of this constraint is the struct keyword ie where T: struct . 这个约束的等价物是struct关键字,即where T: struct But constraining to value types does not gain you anything here. 但是限制价值类型并没有在这里获得任何东西。 And why would it? 为什么会这样呢? There are value types that don't support arithmetic, and there are reference types that do. 有些值不支持算术,并且有一些引用类型。 So being a value-type is orthogonal to what you need. 因此,作为一种价值类型与您需要的正交。

Unfortunately nothing changes with C# 5.0, which is currently in RC state. 不幸的是,C#5.0没有任何变化,目前处于RC状态。 It focused mainly on async programming. 它主要关注异步编程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM