最近我需要一种方法来根据特定的Object属性(在本例中,是DateTime
格式的时间戳)从List中提取不同的值,所以在粗略的谷歌搜索后,我发现了一个so线程,其中有人提供了一个名为"DistinctBy()"的扩展,该扩展遍历集合并返回具有不同属性值的项。代码如下;
<Extension()> _
Public Function DistinctBy(Of TSource, TKey)(source As IEnumerable(Of TSource), keySelector As Func(Of TSource, TKey)) As IEnumerable(Of TSource)
Dim seenKeys As New HashSet(Of TKey)()
For Each element As TSource In source
If seenKeys.Add(keySelector(element)) Then
Return CType(element, Global.System.Collections.Generic.IEnumerable(Of TSource))
End If
Next
End Function
代码最初是用C#编写的,但我使用了代码转换器将其更改为Visual Basic。也就是说,我在VS2013中收到一个警告,指出该函数不会在所有代码路径上返回值。我知道这个错误意味着什么,也知道在正常情况下如何修复它们。然而,考虑到这是一个返回IEnumerable对象的函数,我不确定如何继续。我不熟悉IEnumerable函数是如何工作的,我甚至不知道这个函数是否会工作!
有人能澄清一下这种情况吗?
原始代码包含带有yield
关键字的状态机。同时VB.NET支持它,它是著名的LINQ延迟执行。
<Extension()> _
Public Iterator Function DistinctBy(Of TSource, TKey)(source As IEnumerable(Of TSource), keySelector As Func(Of TSource, TKey)) As IEnumerable(Of TSource)
Dim seenKeys As New HashSet(Of TKey)()
For Each element As TSource In source
If seenKeys.Add(keySelector(element)) Then
Yield element
End If
Next
End Function
如果你必须支持一个不知道Yield
的.NET版本,你可以使用这种方法一次返回所有项目:
<Extension()> _
Public Function DistinctBy(Of TSource, TKey)(source As IEnumerable(Of TSource), keySelector As Func(Of TSource, TKey)) As IEnumerable(Of TSource)
Dim seenKeys As New HashSet(Of TKey)()
Dim list = new List(Of TSource)
For Each element As TSource In source
If seenKeys.Add(keySelector(element))
list.Add(element)
End If
Next
return list
End Function
在最初的C#代码中,它(可能)是一个迭代器方法(使用yield
)
它也应该在VB.Net中为您提供,因此正确的转换将是
<Extension()> _
Public Iterator Function DistinctBy(Of TSource, TKey)(source As IEnumerable(Of TSource), keySelector As Func(Of TSource, TKey)) As IEnumerable(Of TSource)
Dim seenKeys As New HashSet(Of TKey)()
For Each element As TSource In source
If seenKeys.Add(keySelector(element)) Then
Yield element
End If
Next
End Function