【问题标题】:Aggregation and how to check if we can sum objects聚合以及如何检查我们是否可以对对象求和
【发布时间】:2013-09-28 12:22:14
【问题描述】:

我需要编写一个我称之为聚合容器的东西,它存储聚合,这些聚合本质上是采用对象集合并输出单个对象作为结果的操作。聚合的示例包括:算术平均值、一组数字的中值、调和平均值等。这是一个示例代码。

var arithmeticMean = new Aggregation
        {
            Descriptor = new AggregationDescriptor { Name = "Arithmetic Mean" },
            Action = (IEnumerable arg) =>
            {
                double count = 0;
                double sum = 0;

                foreach (var item in arg)
                {
                    sum += (double)item;
                    count++;
                }

                return sum / count;
            }
        };

这是我的代码问题。我假设对象只是双倍的,因此进行了转换。如果他们不是双重的怎么办?如何确保允许我对两个对象求和?标准.Net程序集中是否有某种接口?我需要 ISummable 之类的东西...或者我需要自己实现它(然后我必须包装所有原始类型,如 double、int 等以支持它)。

任何有关此类功能设计的建议都会有所帮助。

【问题讨论】:

  • 问题不在于您需要确定集合是否“可求和”。所有数值本质上都是可累加的。您应该问的问题是“arg 是数字的集合吗?”。您可以尝试为不同的数字类型提供 Action 的强类型变体,或者在 arg 上进行运行时强制转换。
  • 乔恩,谢谢你的回复。我知道,我给出的例子都是数字的……但我真的很想写一些更通用和有用的东西。我不想在那里写一堆运行时强制转换,但我建议一组具有不同类型参数的动作在这里工作......
  • 看看 Enumerable 方法 - 它有一组泛型方法参数化了它支持的每种类型:Sum<int>, Sum<double>, Sum<decimal>, Sum<Nullable<int>> 等。这是使类型参数成为“summable”的唯一方法
  • 这取决于你的目标。如果您假设 arg 必须只包含数字 - 尝试将您的 arg 转换为 IEnumerable。如果出现非数字值,您应该抛出 ArgumentException。
  • @lazyberezovsky +1,虽然我认为这里真正的问题不是如何求和,而是Action 的签名将支持传播类型。

标签: c# .net interface aggregation


【解决方案1】:

看看Enumerable 类方法 - 它有一组方法参数化了它支持的每种类型:

int Sum(this IEnumerable<int> source)
double Sum(this IEnumerable<double> source)
decimal Sum(this IEnumerable<decimal> source)
long Sum(this IEnumerable<long> source)
int? Sum(this IEnumerable<int?> source)
// etc

这是使方法参数成为“可总结”的唯一方法。

不幸的是,您不能使用泛型type parameter constraint 创建一些泛型方法,这将只允许重载 + 运算符的类型。 .NET 中的运算符没有任何限制,运算符也不能是某些接口的一部分(因此它们是静态的)。因此,您不能将运算符与泛型类型的变量一起使用。

此外,如果您查看 .NET 原始类型定义,您将不会在这里找到任何可以帮助您的接口 - 仅实现了比较、格式化和转换:

public struct Int32 : IComparable, IFormattable, IConvertible, 
                      IComparable<int>, IEquatable<int>

【讨论】:

    【解决方案2】:

    您可以在类中修改Action 属性,例如:

    public Func<IEnumerable<double>, double> Action { get; set; }
    

    所以它只会排除IEnumerable&lt;double&gt; 并返回double 结果。

    【讨论】:

    • 我实际上是在尝试从集合的类型中抽象出来,以便我可以总结任何可以以某种方式求和的东西。
    • @george.zakaryan 然后您可以为 Action 创建 2 个重载:Action(IEnumerable&lt;double&gt;)Action(IEnumerable&lt;ISummable&gt;) 其中 ISummable 应该是您的接口。 Double 隐式转换为任何其他数字类型。
    猜你喜欢
    • 1970-01-01
    • 2016-07-25
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    • 2020-04-26
    相关资源
    最近更新 更多