2013-07-18 32 views
6

我有一个代表业务数据的对象。Linq SUM对象?

基本上,它是一个对象agregating有些合计:

public class MyClass{ 
    public double MyDataOne {get;set;} 
    public double MyDataTwo {get;set;} 
    public double MyDataThree {get;set;} 

    public static MyClass operator +(MyClass data1, MyClass data2){ 
     return new MyClass{MyDataOne = data1.MyDataOne + data2.MyDataOne, MyDataTwo=data1.MyDataTwo+data2.MyDataTwo, MyDataThree=data1.MyDataThree+data2.MyDataThree }; 
    } 
} 

现在,如果我有一个IEnumerable<MyClass> myClasses,是有些事我可以在MyClass的实现,使这个:?

myClasses.Sum(d=>d); 

因为对我来说,一个对象additioned的方式必须是对象的知识,而不是调用者(如果有一天,我的一个数据比较多,我不希望在我的整个代码看看看看它在哪里使用)。

谢谢

+0

http://stackoverflow.com/a/13661394/1714342它解释了一些东西 – wudzik

回答

4

写自己的扩展方法:

public static MyClass Sum(this IEnumerable<MyClass> source) 
{ 
    var result = new MyClass(); // all data will be zeros 

    foreach(var item in source) 
     result = result + item; 

    return result; 
} 

用法:

var sum = myClasses.Sum(); 
+1

如果你还可以通过引入一些叫做'可设置'的接口使它更通用化,并为所有'IEnumerable 其中T:可设置':) – wudzik

+1

@wudzik'YAGNI' :)他只有一个这种行为的业务类 –

+0

@wudzik谢谢。我只是补充说我创建了一个接口,以确保我总结的类实现了在参数中带有IEnumerable列表的'Sum'方法。像这样我不创造许多中间元素 – J4N

5

您可以编写一个封装了调用自己的扩展方法来IEnumerable<T>.Aggregate这反过来又要求你超载operator +

public static MyClass Sum(this IEnumerable<MyClass> collection) 
{ 
    return collection.Aggregate((a, b) => a + b); 
} 

这将通过被称为:

MyClass sum = myClasses.Sum(); 

甚至走一步,归纳,并包括一个选择:

public static MyClass Sum<T>(this IEnumerable<T> collection, 
    Func<T, MyClass> selector) 
{ 
    return collection.Aggregate(new MyClass() /*start with an empty MyClass*/, 
     (a, b) => a + selector(b)); 
} 

正如你提到的这被称为:

MyClass sum = myClasses.Sum(d => d); 

以及包含的复杂类型例如:

class Foo 
{ 
    public MyClass Bar {get; set;} 
    public int Baz {get; set;} 
} 

var FooList = new List<Foo>(); 

MyClass sumOfFooListsBars = FooList.Sum(f => f.Bar); 
0

为了使用Sum你应该提供Func<MyClass, ###>代表,其中###intlongfloatdoubledecimal或他们可为空的同行。 所以你不能按照你想要的方式使用MyClass

Sum方法的所有重载都会返回上面提到的基本类型。这就是为什么总结自定义对象没有意义,而返回类型不是数字而是自定义对象。