Linq对象和匿名类型

时间:2010-07-07 20:47:56

标签: linq-to-objects anonymous-types vb.net-2010

我是Linq to Objects的新手,我刚刚遇到了匿名类型和范围的问题。

例如,这很好用:

    Public Sub CreateResults()
        results = From e In CustomerList
                  Join f In OrderList On CustomerList.ID Equals OrderList.ID
                  Select New With {e.FirstName, e.LastName, f.OrderID}

        For Each r in results
            Console.Writeline(r.FirstName, r.LastName, r.OrderID)
        Next t
    End Sub

然而,这不是:

Public Class Foo

    Private _linqResults 

    Public Sub CreateResults()
        _linqResults = From e In CustomerList
                       Join f In OrderList On CustomerList.ID Equals OrderList.ID
                       Select New With {e.FirstName, e.LastName, f.OrderID}
    End Sub

    Public Sub PrintResults()
        For Each r in _linqResults
            Console.Writeline(r.FirstName, r.LastName, r.OrderID)
        Next t
    End Sub

End Class

我一直在寻找SO和其他地方试图找到一个简单的解决方案,没有太多的运气。有没有办法访问包含Linq查询的方法范围之外的匿名类型的字段?类似的东西:

Console.Writeline(r("FirstName").ToString, r("LastName").ToString)

是可以接受的,虽然不理想。

我真的,真的不想开始创建额外的类/结构/ DTO来处理应该是动态查询的内容。

2 个答案:

答案 0 :(得分:2)

无法以您想要的方式推断出类型。你有几个选择:

  1. 制作一个额外的课程(你不想要的)

  2. 更改类的样式,以便CreateResults和PrintResults使用与您相同的方法。但是你有充分的理由不这样做。

  3. 使用动态类型(我想在VB中有一个,但我不确定。我是C#man)然后你可以像在你的例子中那样简单地访问你想要的属性。这显然不如静态输入快。
  4. 有一个黑客(至少在C#中)。但它并不漂亮。请参阅How to return Anonymous Type while using Linq
  5. 您可以使用元组类,而不是使用自定义类。 System.Tuple并将数据存储在那里。他们进来了.Net 4我认为。
  6. 最后我真的认为定制课程是要走的路,除非你有充分的理由不这样做。我还想要一种方法来做同样的事情,但是可以用更新的语法在几行中描述自定义类。

    编辑:添加了几点并稍微改了一下

    请求C#中的动态示例

    class Foo
    {
        private dynamic _linqResults;
    
        public void CreateResults()
        {
            var someData = Enumerable.Range(1, 10);
    
            _linqResults = from i in someData
                           select new
                           {
                               Number = i
                           };
        }
    
        public void PrintResults()
        {
            foreach (var i in _linqResults)
                Console.WriteLine(i.Number);
        }
    }
    

    正如您可能看到的,它几乎与您想要的语法相同。它只是使用动态有点慢 - 但它听起来像你已经使用或将在datagrid和csv中使用某种动态/反射。它的原因取决于您使用的DataGrid和CSV(您自己的?)。

    正如另一个答案所述,编译器无法推断出类型,而且IntelliSense不会成为PrintResults的指南。

    小更新 VB有类似的语法,你可以在这里找到一个很好的步骤: http://blogs.msdn.com/b/vbteam/archive/2008/12/17/walkthrough-dynamic-programming-in-visual-basic-10-0-and-c-4-0-lisa-feigenbaum.aspx

答案 1 :(得分:1)

这是交易。

您正在创建一个匿名类型。编译器只“知道”创建它的范围内的匿名类型。

在第二个示例中,您试图将该匿名类型存储在其创建范围之外。您可以执行此操作,但由于该类型是匿名的,因此除了通过反射之外,您将无法访问编译器生成的属性。

简而言之,如果您希望将linq查询的结果存储在创建范围之外,则必须创建一个类型来保存这些结果。