vb.net - 如何在 VB.Net 中创建一个可以从函数返回结果的 GroupBy?

标签 vb.net linq

我必须编写一个方法,返回按这些对象的某些属性分组的对象列表。我可以使用 linq 的 GroupBy 成功实现它,但使用匿名类型,我无法将其发送回调用者。如果我尝试使用类来存储 IGrouping 部分,如 here 中的建议, .GroupBy 根本不分组 - 就像缺少 Key 关键字一样,但我无法在强类型类中使用它们。

我搜索了很多 - 更多的是因为我懒得写问题,而不是因为遵循 stackoverflow 问题指南 - 但我发现的大多数内容要么与 C# 相关,但没有问题Key 关键字的,或者它是关于单列 GroupBy 的,或者它使用匿名类型,因为它不关心从函数或子函数返回参数,所以我编写了一个小程序来说明这种情况。

Imports System.Globalization

Module Module1

    Public Class TrackHist
        Public Property Data As DateTime
        Public Property Esdvn As String
        Public Property Cmnts As String
        Public Property IdCnt As String
    End Class

    Public Class GroupedTrack
        Public Property Data As DateTime
        Public Property Esdvn As String
    End Class

    Function Group(lista As List(Of TrackHist)) As List(Of IGrouping(Of GroupedTrack, List(Of TrackHist)))
        Return lista.GroupBy(Function(f) New GroupedTrack With {.Data = f.Data, .Esdvn = f.Esdvn}).ToList
    End Function

    Sub Main()
        Dim array As New List(Of TrackHist)
        array.Add(New TrackHist() With {.Data = DateTime.ParseExact("10/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "BIL", .IdCnt = "CN134234"})
        array.Add(New TrackHist() With {.Data = DateTime.ParseExact("10/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "BIL", .IdCnt = "CN284235"})
        array.Add(New TrackHist() With {.Data = DateTime.ParseExact("10/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "BIL", .IdCnt = "CN660003"})
        array.Add(New TrackHist() With {.Data = DateTime.ParseExact("12/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "LOA", .IdCnt = "CN134234"})
        array.Add(New TrackHist() With {.Data = DateTime.ParseExact("12/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "LOA", .IdCnt = "CN284235"})
        array.Add(New TrackHist() With {.Data = DateTime.ParseExact("13/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "LOA", .IdCnt = "CN660003"})
        array.Add(New TrackHist() With {.Data = DateTime.ParseExact("15/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "INSP", .IdCnt = "CN134234"})
        array.Add(New TrackHist() With {.Data = DateTime.ParseExact("16/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "DEP", .IdCnt = "CN284235"})
        array.Add(New TrackHist() With {.Data = DateTime.ParseExact("16/01/2017", "dd/MM/yyyy", CultureInfo.InvariantCulture), .Cmnts = "Nothing", .Esdvn = "DEP", .IdCnt = "CN660003"})

        Dim groupedAnonymous = array.GroupBy(Function(f) New With {Key f.Data, Key f.Esdvn}).ToList
        Dim groupedTyped = Group(array)

        Console.WriteLine("Grouped anonymous: {0} registers", groupedAnonymous.Count)
        Console.WriteLine("Grouped typed: {0} registers", groupedTyped.Count)
    End Sub

End Module

该程序产生以下输出:

匿名分组:5 个寄存器 分组类型:9个寄存器

或者,换句话说,强类型对象的分组根本就不是分组。那么,在 VB.Net 中制作一个可以从函数返回结果的 GroupBy 的正确方法是什么?

最佳答案

将 Slai 和 Mark 的评论转换为答案:

您的问题是您尚未定义将 GroupedTrack 对象与另一个 GroupedTrack 对象进行比较的方法;因此,当创建这些对象时,它们会通过引用进行比较,并且因为它们实际上都是不同的对象,所以您会得到 9 个不同的值。

您要做的就是重写 Equals()GetHashCode() 函数,以便编译器现在如何比较 GroupedTrack按值排列的对象。

类似这样的事情:

Public Class GroupedTrack
    Public Property Data As DateTime
    Public Property Esdvn As String

    Public Overrides Function Equals(obj As Object) As Boolean
        If obj Is Nothing Then Return False
        If TypeOf obj IsNot GroupedTrack Then Return False
        Return Me.Data = CType(obj, GroupedTrack).Data And Me.Esdvn = CType(obj, GroupedTrack).Esdvn
    End Function

    Public Overrides Function GetHashCode() As Integer
        Return (Me.Data.ToString() & Me.Esdvn).GetHashCode()
    End Function
End Class

(当你这样做时,将你的函数定义更正为

Function Group(lista As List(Of TrackHist)) As List(Of IGrouping(Of GroupedTrack, TrackHist))

)

这样,两个分组都会生成一个包含 5 个元素的列表。

关于vb.net - 如何在 VB.Net 中创建一个可以从函数返回结果的 GroupBy?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41266714/

相关文章:

vb.net - MySql.Data.MySqlClient 显示令人困惑的错误

vb.net - 我可以用常量替换 vbLf 和 Chr() 吗?

.net - 通过 .NET HTML5 流式传输 MP4 视频

c# - 如何在可由另一个线程更改的 IEnumerable 上安全地调用 Count(Func)?

c# - 如何使用 foreach 和 LINQ 构建 XDocument?

c# - XML 文档中的多语言示例

.net - 检查图片框图像的索引

c# - LINQ to XML - 根据与另一个 XElement 相比的节点值过滤 XElement?

c# - 在 asp.net core 中插入/更新记录时出错

c# - 延迟执行中的数组子字符串