Linq SUM on objects?

2019-06-17 04:34发布

I've an object that represent a business data.

Basically, it's an object agregating some totals:

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

Now, if I've an IEnumerable<MyClass> myClasses, Is there somethings I can implement in MyClass to make this:?

myClasses.Sum(d=>d);

Because for me, the way an object is additioned must be the knowledge of the object and not the caller(if one day I've one data more, I don't want to look in my whole code to see where it is used).

Thank you

标签: c# .net linq oop sum
3条回答
欢心
2楼-- · 2019-06-17 04:46

You can write your own extension method that wraps a call to IEnumerable<T>.Aggregate which in turn calls your overloaded operator +:

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

This would be called by:

MyClass sum = myClasses.Sum();

Or even go one step further, generalize, and include a selector:

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

This would be called as you suggest:

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

As well as from complex types containing a MyClass for example:

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

var FooList = new List<Foo>();

MyClass sumOfFooListsBars = FooList.Sum(f => f.Bar);
查看更多
小情绪 Triste *
3楼-- · 2019-06-17 05:04

In order to use Sum you should provide Func<MyClass, ###> delegate, where ### is int, long, float, double, decimal or their nullable counterparts. So you are not able to use MyClass in the way you want.

All overloads of Sum method returns primitive types that I mentioned above. That's why it doesn't make sense to sum custom object while returning type is not a number but custom object too.

查看更多
等我变得足够好
4楼-- · 2019-06-17 05:09

Write your own extension method:

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

Usage:

var sum = myClasses.Sum();
查看更多
登录 后发表回答