以下代码遍历一组处理器并返回其ID。硬件探索是危险的,我想使此功能尽可能稳定。那是:
如果在迭代过程中引发了异常,则只需静默跳过此迭代。
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
当前代码无法编译,因为禁止return
在iterator
中使用。
我能想到的最好的是,以取代Return Nothing
通过Yield Nothing
。我希望它会导致包含一个项目的可枚举,这是一个空引用。这是我唯一的选择吗?我知道我可以使用常规函数并在完全迭代后返回集合。这是与练习的练习Iterator
。
Iterator
如果您确实要这样做,我看不出有一种方法可以导致异常返回空集合。如果这样做,您可以停止使用Iterator
和Yield
,只需执行
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
很高兴您声明了该MOS
Using
。作为一个说明,查询结果对象应该以被检查foreach
循环(如在问题示出),然后Dim ProcessorId As String = MyInfo("ProcessorId")?.ToString()
与yield ProcessorId
如果不为空。最后,如果未找到结果,您将得到一个空集合。空的catch块(问题中)很丑陋,不需要。如果捕获到异常(不应该;如果确实得到了,这时出了点问题),则必须评估是否返回null,因为您有部分异常导致的结果。