VB.NET中声明方法始终抛异常以消除BC42105警告的属性
解决VB.NET中BC42105警告的最优方案
问题背景
在.NET 7的VB.NET环境中,编译器警告BC42105会在函数存在既不返回值也不抛出异常的分支时触发。场景是:GetItem函数的Else分支调用了ThrowItemDoesntExist方法(该方法始终抛出异常),但编译器无法自动识别这一点,从而触发警告。
原始代码如下:
Private ReadOnly cgItems As IDictionary(Of Integer, Item) Public Function GetItem(itemID as Integer) As Item Dim item as Item = Nothing If cgItems.TryGetValue(itemID, item) Then Return item Else ThrowItemDoesntExist(itemID) End If End Function Private Sub ThrowItemDoesntExist(itemID As Integer) Throw New ArgumentException($"The Item ID #{itemID} does not exist.", NameOf(itemID)) End Sub
ThrowItemDoesntExist被多处调用用于统一维护,但因为是Sub类型,编译器无法推断它会终止执行流程,导致GetItem触发BC42105警告。
当前临时方案是将ThrowItemDoesntExist改为Function并添加<DoesNotReturn>属性,但这种方式破坏了Sub方法的语义,不够合理。
最优解决方案
直接给原有的Sub方法添加<DoesNotReturn>属性即可,既保留Sub的语义,又能让编译器识别到该方法不会返回:
Imports System.Diagnostics.CodeAnalysis Private ReadOnly cgItems As IDictionary(Of Integer, Item) Public Function GetItem(itemID as Integer) As Item Dim item as Item = Nothing If cgItems.TryGetValue(itemID, item) Then Return item Else ThrowItemDoesntExist(itemID) End If End Function <DoesNotReturn> Private Sub ThrowItemDoesntExist(itemID As Integer) Throw New ArgumentException($"The Item ID #{itemID} does not exist.", NameOf(itemID)) End Sub
修改后,编译器会明确知晓ThrowItemDoesntExist执行后不会继续向下走,GetItem的Else分支不再被判定为存在无返回/无异常的情况,BC42105警告自动消除。
方案优势
- 符合官方规范:
<DoesNotReturn>是System.Diagnostics.CodeAnalysis命名空间下的官方属性,专门用于标记执行后必然终止流程的方法(如始终抛异常的方法)。 - 保留代码语义:无需将Sub改为Function,维持方法“抛出异常而非返回值”的原有意图。
- 维护成本低:一次标记后,所有调用该方法的地方都能被编译器正确识别,无需额外处理。
不推荐的替代方案
若不愿使用属性,可在调用ThrowItemDoesntExist后添加永远不会执行的Return语句,但这属于冗余代码,会降低可读性,不建议采用:
Else ThrowItemDoesntExist(itemID) Return Nothing ' 永远不会执行,仅用于消除编译器警告 End If
内容的提问来源于stack exchange,提问作者Perringaiden
相关产品推荐
相关产品推荐

