【问题标题】:GroupBy anonymous type doesn't work. In C# it's working [duplicate]GroupBy 匿名类型不起作用。在 C# 中它正在工作 [重复]
【发布时间】:2018-01-26 11:47:41
【问题描述】:

我想知道为什么 VB.Net 不能 GroupBy 匿名类型,而 C# 可以。

我在我的 C# 应用程序中做了一堆GroupBys,我通常形成匿名类型,以确保代码的可读性。

现在我在 VB.Net 中做到了。 ruslt:它不起作用。

有人可以解释这种行为吗?

C#-代码:

public class TestObjekt
{
    public int Ean { get; set; }
    public int Size { get; set; }
    public int Amount { get; set; }
}

public static void Main(params string[] args)
{
    List<TestObjekt> objekts = new List<TestObjekt>()
    {
        new TestObjekt() {Ean = 1, Size = 2, Amount = 10},
        new TestObjekt() {Ean = 1, Size = 2, Amount = 100}
    };

    var query = objekts.GroupBy(
        g => new
        {
            Ean = g.Ean,
            Size = g.Size
        },
        (key, group) => new TestObjekt()
        {
            Ean = key.Ean,
            Size = key.Size,
            Amount = group.Sum(s => s.Amount)
        }).ToList();

    // Wo got one object..
    foreach (var q in query)
    {
        Console.WriteLine("Ean: {0}, Size: {1}, Amount: {2}", q.Ean, q.Size, q.Amount);
    }
}

VB.Net-代码:

Public Class TestObjekt
    Public Property Ean() As Int32
    Public Property Size() As Int32
    Public Property Amount() As Int32
End Class

Sub Main()
    Dim objekts As New List(Of TestObjekt)
    objekts.Add(New TestObjekt() With {.Amount = 10, .Ean = 1, .Size = 2})
    objekts.Add(New TestObjekt() With {.Amount = 100, .Ean = 1, .Size = 2})

    Dim query = objekts.GroupBy(
        Function(g) New With
        {
            .Ean = g.Ean,
            .Size = g.Size
        },
        Function(key, group) New TestObjekt() With
        {
            .Ean = key.Ean,
            .Size = key.Size,
            .Amount = group.Sum(Function(s) s.Amount)
        }).ToList()

    'We still got two objects here.

    For Each q As TestObjekt In query
        Console.WriteLine("Ean: {0}, Size: {1}, Amount: {2}", q.Ean, q.Size, q.Amount)
    Next

    query = objekts.GroupBy(
        Function(g) g.Ean.ToString() + "@" + g.Size.ToString(),
        Function(key, group) New TestObjekt() With
                       {
                       .Ean = group.First().Ean,
                       .Size = group.First().Size,
                       .Amount = group.Sum(Function(s) s.Amount)
                       }).ToList()

    'This is working. We Only have one object.

    For Each q As TestObjekt In query
        Console.WriteLine("Ean: {0}, Size: {1}, Amount: {2}", q.Ean, q.Size, q.Amount)
    Next

End Sub

【问题讨论】:

  • 我认为写 FOR 循环是错误的,而不是 GroupBy()。 GroupBy 给出一个二维数组 Group[][]。第一个数组是组,第二个数组是组中的项目。你是一个从每个组中写一个项目而不是所有项目的人。
  • ToList on an Grouping 返回值列表。正如您在 vb 代码中的第二个 for 循环中看到的那样,它工作正常。
  • 不,它没有按照您想要的方式工作。您需要嵌套两个 for 循环才能获得所有结果。
  • 不。 IEnumerable.GroupBy() 返回一个 IEnumerable>。它是“键值对”的“列表”。没有第二个维度。
  • 是的。组中的每个键都可以有一个或多个项目。如果你只有一只母鸡,为什么要使用 Sum()?

标签: c# vb.net anonymous-types


【解决方案1】:

老实说,我很惊讶这在 C# 中有效,而不是惊讶于它在 VB.NET 中不起作用。

这里的关键是编译器生成的类是否以及在何种程度上实现了Equals 和GetHashCode。正如我猜测的那样,这在很大程度上取决于编译器,还取决于您所针对的 .NET 框架版本。如果您的目标是包含新结构元组类型的框架版本,编译器可以使用它们(也就是说,我猜,C# 应用程序中发生了什么)。否则,编译器必须创建旧的编译器生成的类(显然在 VB.NET 中发生了这种情况)。但是可能是VB.NET编译器缺少对元组类型的支持,我根本不知道。

导致此问题的原因是结构元组在代数意义上实现了 Equals 和 GetHashCode - 当且仅当它们的元素相等时,才认为两个元组相等。旧的编译器生成的类型没有实现 Equals 或 GetHashCode,因此,相同元素的两个元组被视为不同。

【讨论】:

  • GetHashCode 在 C# 和 VB 中的工作方式不同。 VB => 只有键属性。 C# => 所有字段。在 S.Akbari 和 Patrick Hofman 显示的问题中正确解释
猜你喜欢
  • 1970-01-01
  • 2011-08-20
  • 1970-01-01
  • 2022-12-18
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
  • 2016-08-31
  • 2013-05-23
相关资源
最近更新 更多