【问题标题】:Linq SUM on objects?对象上的Linq SUM?
【发布时间】:2013-07-17 01:44:44
【问题描述】:

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

基本上,它是一个汇总一些总数的对象:

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

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

谢谢

【问题讨论】:

标签: c# .net linq oop sum


【解决方案1】:

您可以编写自己的扩展方法来包装对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);

以及来自包含MyClass 的复杂类型,例如:

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

var FooList = new List<Foo>();

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

【讨论】:

    【解决方案2】:

    编写你自己的扩展方法:

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

    【讨论】:

    • 如果你还可以通过引入一些名为ISumable 的接口使其更通用,并对所有IEnumerable&lt;T&gt; where T:ISumable 进行通用扩展:)
    • @wudzik YAGNI :) 他只有一个商务舱有这种行为
    • @wudzik 谢谢。我将添加我创建一个接口,以确保我在其上求和的类实现一个Sum 方法,该方法在参数中采用一个 IEnumerable 列表。像这样我不会创建很多中间元素
    【解决方案3】:

    为了使用Sum,您应该提供Func&lt;MyClass, ###&gt; 委托,其中###intlongfloatdoubledecimal 或其可为空的对应项。 所以你不能以你想要的方式使用MyClass

    Sum 方法的所有重载都返回我上面提到的原始类型。这就是为什么在返回类型不是数字而是自定义对象时对自定义对象求和是没有意义的。

    【讨论】:

      【解决方案4】:

      可能有点晚了……

      但如果目标是使用实现的+-函数对类求和(不一定使用Sum()-函数),您可以使用Aggregate()-函数

      List<MyClass> myClasses;
      ...
      
      MyClass myClassSum = myClasses.Aggregate(func: (result, item) => result + item);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-08-19
        • 2011-04-18
        • 1970-01-01
        • 2019-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-11
        相关资源
        最近更新 更多