15

这是一些(显然)无法编译的代码:

var q = from x in myAnonymousTypeCollection
        select new {
          x.ID,
          CalcField = { 
                        switch(x.SomeField) {
                          case 1:
                            return Math.Sqrt(x.Field1);
                          case 2:
                            return Math.Pow(x.Field2, 2);
                          default:
                            return x.Field3;
                        }
                      }
        };

你明白了;我正在尝试以CalcField完全不同的方式进行计算,具体取决于 的值SomeField是什么。我不能使用Func<>(或者我可以吗?),因为输入类型是匿名的。那么让这个工作的正确语法是什么?

4

3 回答 3

13

首先,我通常更喜欢方法链语法而不是 Linq 的查询语法。有了它,您可以轻松地做到这一点。

var q = myAnonymousTypeCollection
    .Select(x => 
            {
                object calcField; 

                 switch(x.SomeField) 
                 {
                      case 1:
                        calcField = Math.Sqrt(x.Field1);
                      case 2:
                        calcField =  Math.Pow(x.Field2, 2);
                      default:
                        calcField = x.Field3;

                 return new 
                        {
                            x.ID,
                            CalcField = calcField
                        };
            });

如果不使用方法链,则需要方法或 Func。让我们假设一个 Func

//replace these with actual types if you can.
Func<dynamic, dynamic> calculateField = 
    x => 
    {
        switch(x.SomeField) {
            case 1:
                return Math.Sqrt(x.Field1);
            case 2:
                return Math.Pow(x.Field2, 2);
            default:
                return x.Field3;
    }

var q = from x in myAnonymousTypeCollection
        select new { x.Id, CalcField = calculateField(x) };

注意:我不是在 IDE 中编写的,所以请原谅任何简单的错误。

这是动态的 MSDN 。但是,我发现一旦需要开始传递匿名类型,最好创建一个实际的类。

于 2013-05-09T16:46:35.727 回答
9

您可以将匿名函数包装为(自执行)Func<>委托。这假设您知道返回类型。

var q = from x in myAnonymousTypeCollection
    select new {
      ID = x.ID,
      CalcField = new Func<double>( () => { 
                    switch(x.SomeField) {
                      case 1:
                        return Math.Sqrt(x.Field1);
                      case 2:
                        return Math.Pow(x.Field2, 2);
                      default:
                        return x.Field3;
                    }
                  } )()
    };
于 2013-05-09T16:47:00.973 回答
1

您可以很容易地将开关逻辑移出到另一个函数中,如下所示:

private static T GetReturnValue<T>(myClass x)
{
    switch (x)
    {
        case 1:
            return Math.Sqrt(x.Field1);
            break;
        case 2:
            return Math.Pow(x.Field2,
                            2);
            break;
        default:
            return x.Field3;
            break;
    }
}

然后你只需要将你的对象传递给那个函数来取回你想要的值:

var q = from x in myAnonymousTypeCollection
                    select new
                        {
                            ID = x.ID,
                            CalcField = GetReturnValue(x)
                        };
于 2013-05-09T16:53:04.627 回答