Linq to 对象和匿名类型

发布于 2024-09-08 09:53:48 字数 1175 浏览 2 评论 0原文

我是 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 来处理动态查询。

I'm new to Linq to Objects, and I've just hit the problem of anonymous types and scope.

For example, this works just fine:

    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

This however does not:

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

I've been looking through SO and other places trying to find a simple solution to this without much luck. Is there any way to access the fields of an anonymous type outside the scope of the method containing the Linq query? Something like:

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

would be acceptable, though not ideal.

I really, really don't want to start creating additional classes/structures/DTOs to handle what are supposed to be dynamic queries.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晨曦÷微暖 2024-09-15 09:53:48

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

  1. 创建一个额外的类(您不需要)

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

  3. 使用动态类型(我猜 VB 中有一个,但我不确定。我是一名 C# 人员),然后您可以像在示例中那样简单地访问所需的属性。这显然不如静态类型快。

  4. 有一个 hack 可以做到这一点(至少在 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 中的指南。

小更新
VB 有类似的语法,您可以在这里找到一个很好的示例:
链接

It is not possible to infer the types the way you want. You have a few choices though:

  1. Make a additional class (which you don't want)

  2. Change the style of the class so CreateResults and PrintResults is in the same method as you have done. BUT you properly have a good reason not to do that.

  3. Use the dynamic type (I guess there is one in VB, but I don't know for sure. I'm a C# man) and then you simple access the properties you want as you do in your example. This is obviously not as fast as static typing.

  4. There is a hack to do it (at least in C#). But it is not pretty. See How to return Anonymous Type while using Linq

  5. Instead of using a custom class you could use the tuple classes. System.Tuple and store the data there. They came in .Net 4 I think.

In the end I really think a custom class is the way to go unless you have a good reason not to. I would also like a way to do the same thing you want to, but a custom class can be described in a few lines with newer syntax.

EDIT: Added a few points and changed a little bit

Example with dynamic in C# as requested

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);
    }
}

As you maybe see, it is almost the same syntax as you want. It just uses dynamic which is a bit slower - but it sounds like that you already uses or will use some kind of dynamic/reflection in datagrid and csv. It of cause depends on which DataGrid and CSV (your own?) you use.

As mentioned in another answer, the compiler can't infer the types and IntelliSense will not be your guide in PrintResults.

Little update
VB has a similar syntax which you can find a good walk-trough with here:
Link

七禾 2024-09-15 09:53:48

事情是这样的。

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

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

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

Here's the deal.

You're creating an anonymous type. The compiler only "knows" about the anonymous type within the scope in which it is created.

In the second example, you are attempting to store that anonymous type outside of the scope of its creation. You can do this, but since the type is anonymous you lose the ability to access the compiler-generated properties except via reflection.

Long story short, if you wish to store the results of a linq query outside of the scope it is created, you must create a type to hold those results.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文