【问题标题】:Implicit Conversion: Nullable(Of T) => T | VB.NET LINQ Query Syntax Vs Method Syntax隐式转换:Nullable(Of T) => T | VB.NET LINQ 查询语法与方法语法
【发布时间】:2015-08-26 05:19:52
【问题描述】:

方法语法会阻止隐式转换,但查询语法不会。 Option Strict 已开启。 如何在使用查询语法时强制显示错误?

整个(完全可运行)程序:

Option Strict On

Module Module1

Sub Main()

    Dim custList As New List(Of Cust)()
    custList.Add(New Cust() With {.Name = "Mr. Current", .Deleted = False})
    custList.Add(New Cust() With {.Name = "Mrs. Deleted", .Deleted = True})
    custList.Add(New Cust() With {.Name = "Miss Null", .Deleted = Nothing})

    Dim QuerySyntax =
        From c In custList
        Where c.Deleted = False 'no error (the problem)

    Dim MethodSyntax =
        custList _
        .Where(Function(c) c.Deleted = False) 'compiler error (desired effect)

    For Each c As Cust In QuerySyntax
        Console.WriteLine("Q: " & c.Name & " " & c.Deleted)
    Next

    For Each c As Cust In MethodSyntax
        Console.WriteLine("M: " & c.Name & " " & c.Deleted)
    Next

    Console.ReadKey(True)

End Sub

Class Cust
    Public Property Name() As String
    Public Property Deleted() As System.Nullable(Of Boolean)
End Class

End Module

问题的关键所在:

Where c.Deleted = False 'no error
.Where(Function(c) c.Deleted = False) 'compiler error

【问题讨论】:

  • 不是比较让编译器感到不安,而是将一个返回 Boolean? 的 lambda 函数传递给一个接受返回 Boolean 的 lambda 的方法。在第一种情况下,没有函数传递,所以也没有错误。我怀疑你能解决这个问题。
  • 我在这里可能有点离谱,但在第一种语法中,是否正在发生隐式装箱操作,使得编译器决定它不必识别隐式转换?也就是说,如果(由于某种原因)在“where c.Deleted = False”中有一个隐式框,则 Nullable 问题(对或错)被排除,因此没有编译器错误....
  • 感谢@GSerg 的澄清,它看起来确实比较有效,但返回了Boolean? 我在这个简化的示例中查看了调试器:New Nullable(Of Boolean)(Nothing) = False 并确认它返回了Boolean? False的值

标签: vb.net linq implicit-conversion linq-query-syntax linq-method-syntax


【解决方案1】:

我至少会竭尽全力,并表示我已经找到了这种行为的解释。

我使用这段代码并在QuerySyntax 版本中更改了'c.Deleted = Nothing',并立即得到一个“绿色波浪”,上面写着“This expression will always evaluate to Nothing due to null propagation of the equals operator.”,这让我开始思考编译器是如何解释表达式的,所以我做了稍微窥探了一下,发现如下:

VB.Net Linq to Entities Null Comparison - 'Is Nothing' or '= Nothing'?

从那篇文章看来,当Nullable(Of T) 涉及表达式时,编译器在内部提升(或者,我想,更准确地说,“提升”)相等运算符Nullable(Of T) 版本,我认为从技术上讲,它不是“隐式转换”。因此,它不会生成编译时错误。因为元素作为parameter 传递给MethodSyntax 版本中的函数,所以没有应用提升运算符,然后编译器会捕获隐式转换语法。

【讨论】:

  • 使用更严格的编译器设置会捕捉到这种奇怪的行为吗?
  • 我不知道。我想,这将是一个问题,这是否是故意的差异;可以推断在这两种情况下使用或不使用提升运算符的决定应该是相同的,这意味着允许的第一个语法是一个解析树,它不应该真正通过选项严格检查。
【解决方案2】:

感谢@David W 的 cmets,他们帮我指出了答案!

方法语法:

.Where 方法具体为System.Linq.Enumerable.Where 方法,它指定predicate 参数是一个返回Boolean 值的labmba 函数。正如@GSerg 所说,比较将返回一个Boolean? 值,因此编译器会抛出一个错误。

MSDN: Extension Method

查询语法

相比之下,查询语法的Where 子句接受“表达式”作为条件参数。

关于这个 condition 参数,MSDN 继续说:

在 Where 子句中使用的表达式必须计算为 布尔值或布尔值的等效值,例如整数 当其值为 0 时,计算结果为 False。

MSDN: Where Clause

结论

换句话说,使用查询语法,表达式将始终被计算。因此,Option Strict 将不起作用,因为编译器正在考虑计算表达式的 result,而不是表达式本身的数据类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    • 2014-03-25
    • 2011-04-16
    • 1970-01-01
    相关资源
    最近更新 更多