Hei*_*nzi 7 vb.net language-lawyer roslyn
请考虑以下代码示例:
Function f1() As Object ' yields warning BC42353
End Function
Function f2() As Int32 ' yields warning BC42353
End Function
Function f3() As DateTime ' yields warning BC42353
End Function
Function f4() As Guid ' no warning
End Function
Run Code Online (Sandbox Code Playgroud)
以及以下项目设置:
显然,VB.NET在以下三类类型之间有所不同:
并为1 + 2提供"缺失返回值"警告,但不提供3(不提供此类编译器选项).
语言设计者决定在这类类型中省略此功能的"非内在价值类型"有什么特别之处?
(我怀疑这是一个深思熟虑的决定,因为(我假设)为所有值类型实现该功能要比检查一些硬编码的"内在"白名单更容易.)
鉴于 Roslyn VB 编译器流分析源代码的源代码,特别是在数据流传递中,可以在第 1232 行中找到该源代码,启动决定是否应生成此警告的子程序。请注意,我假设是基于我在存储库中执行的各种搜索。
if 语句从第 1250 行开始,如下所示:
If type.IsIntrinsicValueType Then
Select Case MethodSymbol.MethodKind
Case MethodKind.Conversion, MethodKind.UserDefinedOperator
warning = ERRID.WRN_DefAsgNoRetValOpVal1
Case MethodKind.PropertyGet
warning = ERRID.WRN_DefAsgNoRetValPropVal1
Case Else
Debug.Assert(MethodSymbol.MethodKind = MethodKind.Ordinary OrElse MethodSymbol.MethodKind = MethodKind.LambdaMethod)
warning = ERRID.WRN_DefAsgNoRetValFuncVal1
End Select
ElseIf type.IsReferenceType Then
Select Case MethodSymbol.MethodKind
Case MethodKind.Conversion, MethodKind.UserDefinedOperator
warning = ERRID.WRN_DefAsgNoRetValOpRef1
Case MethodKind.PropertyGet
warning = ERRID.WRN_DefAsgNoRetValPropRef1
Case Else
Debug.Assert(MethodSymbol.MethodKind = MethodKind.Ordinary OrElse MethodSymbol.MethodKind = MethodKind.LambdaMethod)
warning = ERRID.WRN_DefAsgNoRetValFuncRef1
End Select
ElseIf type.TypeKind = TypeKind.TypeParameter Then
' IsReferenceType was false, so this type parameter was not known to be a reference type.
' Following past practice, no warning is given in this case.
Else
Debug.Assert(type.IsValueType)
Select Case MethodSymbol.MethodKind
Case MethodKind.Conversion, MethodKind.UserDefinedOperator
' no warning is given in this case.
Case MethodKind.PropertyGet
warning = ERRID.WRN_DefAsgNoRetValPropRef1
Case MethodKind.EventAdd
' In Dev11, there wasn't time to change the syntax of AddHandler to allow the user
' to specify a return type (necessarily, EventRegistrationToken) for WinRT events.
' DevDiv #376690 reflects the fact that this leads to an incredibly confusing user
' experience if nothing is return: no diagnostics are reported, but RemoveHandler
' statements will silently fail. To prompt the user, (1) warn if there is no
' explicit return, and (2) modify the error message to say "AddHandler As
' EventRegistrationToken" to hint at the nature of the problem.
' Update: Dev11 just mangles an existing error message, but we'll introduce a new,
' clearer, one.
warning = ERRID.WRN_DefAsgNoRetValWinRtEventVal1
localName = MethodSymbol.AssociatedSymbol.Name
Case Else
warning = ERRID.WRN_DefAsgNoRetValFuncRef1
End Select
End If
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,不生成警告的唯一条件是类型 TypeKind 属性等于 TypeParameter。我真的不太了解这些类型,但我假设 .NET 框架中有一些类/类型(GUID 必须是其中之一)具有这种行为方式。
这似乎根本不是一个决定,而是编译器在某些类型中的设计行为。然而,我可以从代码中看到,根据方法的类型(在本例中为函数)添加警告并不难,而不管返回类型,我认为这是最好的做法。
希望这可以帮助。