2009-05-27 14 views
4

有沒有辦法做到這一點?如何限制通用參數來實現基本的數學運算符?

我想有一個T的集合類,它能夠在T類型上進行加法,減法。我想保持T泛型,而不是使用相同的代碼,但不同類型的夫婦集合。

你會如何約束泛型T?

例如:我想定義一個Collection(T爲IDoMaths)。我不想用命名方法創建自己的整數等類來完成這些操作,因爲我認爲它會變慢。這部分代碼實際上經常被調用,並且往往是性能的瓶頸。

回答

7

不幸的是,你不能。

有一種解決方法,Marc Gravell將implemented作爲MiscUtil的一部分(也有more general article)。它很整潔,但你確實失去了靜態類型檢查。

與此類似(失去類型檢查換算)爲C#4.0新dynamic功能可讓您使用運營商以任意方式,只有在執行時解決這些問題:

dynamic x = 10.0; 
dynamic y = 3.0; 
double z = x/y; // z = 3.3333333 (double arithmetic) 

dynamic a = 10; 
dynamic b = 3; 
int c = a/b; // c = 3 (integer arithmetic) 

就在今天下午我用它來實現Enumerable.Sum的動態表單。我即將對它進行基準測試。 Marc Gravell最近也寫了一篇關於這個的blog post

如果您使用的是VB,可能只需將代碼段的Option Strict關閉,您希望後期綁定會產生相同的效果,但我不熟悉VB,因爲我使用C#,I '我害怕。

+0

這是一個令人失望的限制,在當前泛型的實現。馬克的實施是我見過的最好的處理問題。有關connect.microsoft.com的一些支持文章與此相關。你可以在這裏找到它們:http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=94264和這裏:http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID= 325177和這裏:http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=338861。 – LBushkin 2009-05-27 21:23:35

+0

你是否打算使用動態的int示例? – 2009-05-27 21:47:50

4

如果你想要一個更直接,但涉及多一點冗餘的替代解決方案,你可以嘗試一些我剛剛掀起來的東西。這裏的一個優點是它完全類型安全。

這是一個快速的髒版本,它爲int和float實現了+和 - 操作。將它擴展到包含更多的操作以及支持更多的原始類型(雙精度,十進制等)或甚至自定義類型都應該是微不足道的。只需用您需要的任何東西替換GenericMath即可。

class Program 
{ 
    static void Main(string[] args) 
    { 
     var gsInt = new GenericMath<int,IntOperators>(); 
     var gsFloat = new GenericMath<float,FloatOperators>(); 

     var intX = gsInt.Sum(2, 3); 
     var floatX = gsFloat.Sum(2.4f, 3.11f); 
    } 
} 

interface IOperators<T> 
{ 
    T Sum(T a, T b); 
    T Difference(T a, T b); 
} 

sealed class IntOperators : IOperators<int> 
{ 
    public int Sum(int a, int b) { return a + b; } 
    public int Difference(int a, int b) { return a - b; } 
} 

sealed class FloatOperators : IOperators<float> 
{ 
    public float Sum(float a, float b) { return a + b; } 
    public float Difference(float a, float b) { return a + b; } 
} 

class GenericMath<T,Y> 
    where Y : IOperators<T>, new() 
{ 
    private readonly static Y Ops = new Y(); 

    public T Sum(T a, T b) 
    { 
     return Ops.Sum(a, b); 
    } 

    public T Difference(T a, T b) 
    { 
     return Ops.Difference(a, b); 
    } 
}