执行Ienumerable <datarow> .Sum()方法时出错。</datarow>

时间:2010-08-19 12:02:48

标签: c# linq generics lambda

为什么以下代码不起作用?我收到以下错误。

  

无法将类型'V'隐式转换为int。

private ObservableCollection<DataItem> method<T, V>(DataTable dt, SeriesItem seriesItem, FilterValues filter, ObservableCollection<DataItem> chart)
{
    var result = from t in dt.AsEnumerable()
                 group t by new { type = t.Field<T>(seriesItem.LabelMapping).ToString().ToUpper() } into g
                 orderby g.Key.type
                 select new
                 {
                     Item_Type = g.Key.type.ToString(),
                     Amount = seriesItem.IsSum 
                          ? g.Sum(s => s.Field<V>(seriesItem.ValueMapping)) 
                          : g.Count()
                 };

    foreach (var g in result) 
    { 
        chart.Add(new DataItem(g.Item_Type, double.Parse(g.Amount.ToString()))
                  { 
                      IsSum = seriesItem.IsSum, 
                      IsDisplayCurrency = seriesItem.IsDisplayCurrency 
                  }); 
    }
    return chart;
}

3 个答案:

答案 0 :(得分:0)

g.Count()返回一个int

IsSum ? g.Sum() : g.Count()必须是int

所以g.Sum()必须是int

所以V必须是int

除了这个演绎之外没有任何东西可以阻止V成为decimal或其他任何内容,因此编译错误消息。

修复:以下任何一个:

  • 删除V并获取int结果
  • 删除g.Count()
  • 将g.Count()转换为double并将V的类型修改为double。

最后一个有一个额外的好处,你可以在以后的方法中删除双转换代码。


@Daniel Renshaw

List<decimal> source = new List<decimal>();
int result = source.Sum<decimal>();  //compile error
  //Cannot implicitly convert type 'decimal' to 'int'

答案 1 :(得分:0)

问题在于你试图总结所有V型值。

s.Field<V>(...)返回类型为V的值,因此选择器匿名函数s => s.Field<V>(...)也返回类型为V的值。但是,g.Sum(...)需要一个返回值为1的选择器函数以下类型:decimaldoublefloatintlong(或其可以为空的对应方)。无法从类型V隐式转换为任何类型。

如果值映射列始终是特定类型,则显式使用该类型而不是泛型类型V.

答案 2 :(得分:0)

查看你的代码,我猜这段代码会返回一个类型为V的值:

s => s.Field<V>(seriesItem.ValueMapping)

如果是这种情况,假设对类型V没有约束(可能是任何东西,对象,字符串等等),编译器将无法确定哪个重载{{3}调用方法,因此编译错误。

假设V的类型仅在运行时已知(因此您不能简单地将V约束为int / decimal / double等)如何向该方法添加委托,您可以使用该委托从一个对象返回一个int V型? e.g:

private ObservableCollection<DataItem> method<T, V>(DataTable dt, SeriesItem seriesItem, FilterValues filter, ObservableCollection<DataItem> chart, Func<V, int> convertV)
    {
        var result = from t in dt.AsEnumerable()
                     group t by new { type = t.Field<T>(seriesItem.LabelMapping).ToString().ToUpper() } into g
                     orderby g.Key.type
                     select new
                     {
                         Item_Type = g.Key.type.ToString(),
                         Amount = seriesItem.IsSum ? g.Sum(s => convertV(s.Field<V>(seriesItem.ValueMapping))) : g.Count()
                     };

然后你将责任推送给调用者(它会知道类型T和V)以找出如何将V转换为int。