2009-05-27 68 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); 
    } 
}