1

我是 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 来处理应该是动态查询的内容。

4

2 回答 2

2

不可能以您想要的方式推断类型。不过,您有几个选择:

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

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

  3. 使用动态类型(我猜在 VB 中有一个,但我不确定。我是 C# 人),然后您可以像在示例中那样简单地访问所需的属性。这显然不如静态类型快。
  4. 有一个技巧可以做到(至少在 C# 中)。但这并不漂亮。请参阅如何在使用 Linq 时返回匿名类型
  5. 您可以使用元组类,而不是使用自定义类。System.Tuple 并将数据存储在那里。我认为他们来自.Net 4。

最后,我真的认为自定义类是要走的路,除非你有充分的理由不这样做。我也想要一种方法来做你想做的事情,但是自定义类可以用更新的语法用几行来描述。

编辑:添加了几点并进行了一些更改

根据要求在 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);
    }
}

如您所见,它几乎与您想要的语法相同。它只是使用慢一点的动态 - 但听起来您已经使用或将在数据网格和 csv 中使用某种动态/反射。它的原因取决于您使用哪个 DataGrid 和 CSV(您自己的?)。

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

Little update 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

于 2010-07-07T20:55:30.870 回答
1

这是交易。

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

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

长话短说,如果您希望将 linq 查询的结果存储在它创建的范围之外,您必须创建一个类型来保存这些结果。

于 2010-07-07T20:56:33.927 回答