2013-07-18 14 views
6

私はビジネスデータを表すオブジェクトを持っています。オブジェクトのLinq SUM?

基本的に、それはいくつかの合計をagregatingオブジェクトだ:私はIEnumerable<MyClass> myClassesをした場合

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

、私はこれを行うためにはMyClassに実装することができ代はあり:?

myClasses.Sum(d=>d); 

私のために、オブジェクトがadditionedされている方法は、オブジェクトの知識ではなく、発信者でなければならないので(1日、私は、1つのデータより、私は私の全体のコードで見たくないしている場合それが使用されている場所を確認する)。

は、独自の拡張メソッドを書くあなた

+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

を説明し、あなたもISumable' 'と呼ばれるいくつかのインターフェースを導入することによって、それがより汎用的にすると、すべての' IEnumerableをのための汎用的な拡張を作ることができればここで、T:ISumable ':) – wudzik

+1

@ wudzik' YAGNI' :)この行動のビジネスクラスは1つしかありません –

+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

あなたは###intlongfloatdoubledecimalまたはそのNULL可能対応ですFunc<MyClass, ###>デリゲートを、提供しなければならないSum使用するためには。 MyClassをあなたが望むように使用することはできません。

Sumのすべてのオーバーロードは、上記のプリミティブ型を返します。そのため、戻り値の型は数値ではなくカスタムオブジェクトでも、カスタムオブジェクトを合計するのは意味がありません。