[英]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.