温馨提示:本文翻译自stackoverflow.com,查看原文请点击:.net - Make Iterator function to return a null reference when an exception is thrown
.net vb.net

.net - 使Iterator函数在引发异常时返回空引用

发布于 2020-04-04 11:06:23

以下代码遍历一组处理器并返回其ID。硬件探索是危险的,我想使此功能尽可能稳定。那是:

  • 如果在准备迭代时引发了异常,则返回空引用;否则,返回null。
  • 如果在迭代过程中引发了异常,则只需静默跳过此迭代。

    Public ReadOnly Iterator Property ProcessorIds As IEnumerable(Of String) Implements IHardwareIds.ProcessorIds
        Get
    
            Try
    
                Dim BiosQuerry As ObjectQuery = New SelectQuery("Win32_Processor") 'https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-processor
                Dim HardwarePieces As New ManagementObjectSearcher(BiosQuerry)
    
                For Each MyInfo As ManagementObject In HardwarePieces.Get
                    Try
                        Dim ProcessorId As String = MyInfo("ProcessorId").ToString
                        Yield ProcessorId
                    Catch ex As Exception
                    End Try
                Next
    
            Catch ex As Exception
                Return Nothing
            End Try
    
        End Get
    End Property
    

当前代码无法编译,因为禁止returniterator中使用。

我能想到的最好的是,以取代Return Nothing通过Yield Nothing我希望它会导致包含一个项目的可枚举,这是一个空引用。这是我唯一的选择吗?我知道我可以使用常规函数并在完全迭代后返回集合。这是与练习的练习Iterator

查看更多

提问者
Ama
被浏览
121
djv 2020-01-31 06:32

Iterator如果您确实要这样做,我看不出有一种方法可以导致异常返回空集合。如果这样做,您可以停止使用IteratorYield,只需执行

Public ReadOnly Property ProcessorIds As IEnumerable(Of String) Implements IHardwareIds.ProcessorIds
    Get
        Try
            Using s As New ManagementObjectSearcher(New SelectQuery("Win32_Processor"))
                Return s.Get().OfType(Of ManagementObject).Select(Function(o) o("ProcessorId").ToString())
            End Using
        Catch
            Return Enumerable.Empty(Of String)
        End Try
    End Get
End Property

在不使用LINQ的情况下使用LINQ Iterator实际上允许您删除For Each和简化代码。

(如果您希望返回null,则几乎相同)

Public ReadOnly Property ProcessorIds As IEnumerable(Of String) Implements IHardwareIds.ProcessorIds
    Get
        Try
            Using s As New ManagementObjectSearcher(New SelectQuery("Win32_Processor"))
                Return s.Get().OfType(Of ManagementObject).Select(Function(o) o("ProcessorId").ToString())
            End Using
        Catch
            Return Nothing
        End Try
    End Get
End Property

但是,返回null与其他Enumerable函数(例如Where@,如@ Anu6is指出,当谓词不被任何元素满足时将返回空集合)有不同的感觉

您也可以在第一个异常发生时停止迭代。如果Yield从未命中,那么您的结果将是一个空集合。我认为这更符合的精神Iterator

Public ReadOnly Iterator Property ProcessorIds As IEnumerable(Of String) Implements IHardwareIds.ProcessorIds
    Get
        Try
            Using s As New ManagementObjectSearcher(New SelectQuery("Win32_Processor"))
                For Each mo In s.Get()
                    Yield mo("ProcessorId").ToString()
                Next
            End Using
        Catch
            Return ' or Exit Property
        End Try
    End Get
End Property

C#模拟是产量下降;而且看起来很干净。另请参阅此答案