簡體   English   中英

在C#5.0中改進了泛型類型的功能/運算符重載嗎?

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

我知道有很多關於這樣的問題
"Operator 'whatever' cannot be applied to operands of type 'T' (無論是++,+ =或<=等等。但請耐心等待,我想問一些不同的東西。

假設我有這個代碼

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

即使我已經創建了我的類型結構,並且值類型I得到錯誤Operator '+=' cannot be applied to operands of type 'T' and 'T'

如果我嘗試細微並應用ValueType約束,則表示Constraint cannot be special class 'System.ValueType'

如果我嘗試將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;
    }
}

我仍然得到錯誤

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一起發布(據我所知他們仍然處於測試階段?)它會處理這些問題嗎? 或者我們是否再次對泛型的使用有如此多的限制?

沒有語言改進是可能的,但你必須使用一些技巧,不能將它應用於現有的數字類型,但必須創建新的。 其中之一是奇怪的重復模式class C<T> : where T : C<T> 另一個技巧是使用靜態委托進行操作。 我定義了一個這樣的數字類(為了簡單起見,我只定義了添加):

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

請注意,在重載運算符時,我們必須至少指定一個類型為Numeric<T> (一種類型必須始終是重載運算符的類)。 另請注意,由於where T : Numeric<T>的通用約束,我們可以將Numeric<T>T

現在我們可以聲明這樣的計算器。 由於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;
    }
}

現在讓我們定義一個具體的Numeric類。 在靜態構造函數中,我們定義靜態Add委托。 由於運算符是靜態的,因此該委托也必須是靜態的,因為它是在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);
    }
}

現在讓我們來測試這個棘手的構造

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將提供async-await和一些次要功能。 但不是與方法/運算符重載一起使用的泛型的擴展版本。

對於比較,您可以使用IComparer<T>IComparable<T>作為解決方法,但對於算術,沒有好的解決方案。 有一些技術,但它們要么使API丑陋,要么它們很慢。


如果我試圖微妙並應用ValueType約束,它說“約束不能是特殊類System.ValueType

這個約束的等價物是struct關鍵字,即where T: struct 但是限制價值類型並沒有在這里獲得任何東西。 為什么會這樣呢? 有些值不支持算術,並且有一些引用類型。 因此,作為一種價值類型與您需要的正交。

不幸的是,C#5.0沒有任何變化,目前處於RC狀態。 它主要關注異步編程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM