有泛型类型的功能/运算符重载改进在C#5.0? [英] Has generic type's features/operator overloading improved in C# 5.0?

查看:446
本文介绍了有泛型类型的功能/运算符重载改进在C#5.0?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道有很多问题,像这样的

操作符'任何'不能应用于类型'T'的操作数

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.

假设我有这个代码

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

即使我创建了我的类型结构,值类型我得到错误
运算符'+ ='不能应用于类型'T'和'T'的操作数

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'

微妙并应用ValueType约束,它说
约束不能是特殊类'System.ValueType'

If I try to be subtle and apply the ValueType constraint, it says Constraint cannot be special class 'System.ValueType'

如果我尝试将for循环中的参数转换为类型T,并执行此操作。

If I try to turn the parameter in for loop to type T, and do this..

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

我仍然会收到错误

运算符<'不能应用于类型'T'和'int'的操作数

运算符'++'不能应用于类型'T'的操作数

不能将类型'T'隐式转换为'int' / code>

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'

无论如何,我不能让它工作。我使用VS2010(C#4.0,.NET 4.0)。所以我想知道当C#5.0将终于与VS2012发布(据我所知,他们仍然在测试阶段对吗?)它会照顾这些问题吗?

No matter what, I can't get it to work. I am using 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? Or are we again left with so many restriction on usage of Generics?

推荐答案

这是没有语言改进的可能,但你必须使用一些技巧,不能应用于现有的数字类型,但必须创建新的。其中之一是好奇地重现的模式 class C< T> :其中T:C T 。另一个窍门是使用静态委托进行操作。我定义一个类似这样的数字类(为了简单起见,我只定义添加):

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

注意,我们必须至少指定一个类型当重载操作符时(一个类型必须始终是重载操作符的类),数字< T> 。还要注意,我们可以将 Numeric 转换为 T ,因为通用约束 T:Numeric< T>

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). Note also that we can cast Numeric<T> to T because of the generic constraint where T : Numeric<T>

现在我们可以声明一个这样的计算器。由于 Numeric< T> 重载 + 运算符,我们可以使用 + = 这里。

Now we can declare a calculator like this. Since Numeric<T> overloads the + operator, we can use += 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;
    }
}

现在可以定义一个具体的Numeric类。在静态构造函数中,我们定义了 Add 委托。因为运算符是静态的,所以这个委托也必须是静态的,因为它是从运算符方法内调用的,而且由于静态成员不能是虚拟的,因此我们必须使用这个委托技巧。

Now lets define a concrete Numeric class. In the static constructor we define the static Add delegate. 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.

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)

    }
}

这篇关于有泛型类型的功能/运算符重载改进在C#5.0?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆