【问题标题】:Is there a VB.NET expression that *always* yields null?是否有一个 *always* 产生 null 的 VB.NET 表达式?
【发布时间】:2014-03-03 13:11:58
【问题描述】:

我们都知道 VB 的 Nothing 与 C# 的 null 相似但不等价。 (如果您不知道,请先查看this answer。)

出于好奇,我想知道以下内容:

是否存在始终产生 null 的 VB.NET 表达式?


举个具体的例子,下面的说法:

Dim o As Object = If(myBool, 5, ...)

是否可以用某些东西替换...,例如myBool 为真时o5myBool 为假时Nothing/null

明显无效的解决方案:

  • Nothing(请参阅上面链接答案的问题),
  • DirectCast(Nothing, Object)(在 Option Strict On 的情况下引发编译时错误),
  • DirectCast(Nothing, Integer?) 适用于本示例,但不适用于一般情况(如果在本示例中将 5 替换为 5.0,则需要修改演员表)。

明显的解决方法(不计入答案):

  • 声明一个Object变量或字段,将其设置为Nothing并将其用于...
  • 定义一个总是返回Nothing的方法或属性,
  • DirectCast第二个参数(5)改为Object

注意:上面的例子只是一个例子。问题本身用粗体书写。

【问题讨论】:

  • 您想要一个既适用于引用类型又适用于值类型的单线器?如果值类型不可为空怎么办?你能展示一下这段代码的用法吗?
  • 你的问题不是很清楚,为什么你需要总是得到null?使用可空类型而不是对象有什么问题?如果您的示例是可互换的,请提供一个更好的示例,其中 Int32? 不是一个选项。
  • @TimSchmelter:我想在编写自动 C#->VB.NET 转换器时类似的东西可能很有用,但主要是我只是好奇。我看不出问题是如何不清楚的:“VB.NET 表达式”定义明确,并且在问题中明确说明了表达式所需的返回值。
  • 如果您链接的答案是Nothing和null之间的唯一区别,那么这个问题没有意义。对于任何可能产生 null 的类型,default(T) 都会产生 null。所以你要问的基本上是:“是否有一个 VB.NET 表达式不仅会为可能的类型产生 null,而且不会产生 null 的类型?”
  • @TimSchmelter:“不,绝对没有这样的表达”将是一个完美的答案。

标签: c# .net vb.net


【解决方案1】:

我给出的第一个答案错过了一些点,但应该这样做:

Dim o As Object = If(myBool, 5, DirectCast(Nullable.GetUnderlyingType(GetType(Integer)), Object))

这使用了这样一个事实,即Nullable.GetUnderlyingType 将返回一个空引用,如果你向它传递一个不是可空值类型的类型 - Integer 不是。存在其他替代方案,例如Type.GetElementType(),或者可能是GetType(Object).BaseType

我已经检查过这适用于第二个操作数的多种不同类型。

您必须转换为Object,这有点烦人...我仍在研究替代方案...

【讨论】:

  • @Heinzi:啊——那一点的目的对我来说并不明显。你可以把它放到一个通用方法中吗? (这肯定比所有这些乱七八糟的事情要简单。)
  • @Heinzi:实际上,如果您将其更改为 5.0,此代码仍然有效。
  • @Heinzi:啊 - 我没有 Option Strict On。忽略我之前的评论:(
  • @JonSkeet:正如我所说,我只是好奇这样的表达是否存在。我知道有多种方法可以解决这个问题。
  • @Heinzi:是的,我找到了。现在编辑:)
【解决方案2】:

简单的答案是,不。 VB.NET 中没有只返回null 的表达式。如您所知,当编译器使用三元运算符解析命令时,它会根据两个输入推断输出类型。如果两个输入之一是Nothing,则它必须仅依赖于另一个参数。因此,在 VB.NET 中“正确”的做法是首先将另一个参数强制转换为Object,从而强制操作的输出为Object

Dim o As Object = If(myBool, DirectCast(5, Object), Nothing)

但是,如果您确实需要一个内联表达式,它本身的计算结果始终为 null,您始终可以通过调用 lambda 表达式来实现,如下所示:

Dim o As Object = If(myBool, 5.0, (Function() Nothing).Invoke())

该语法应该在任何情况下都有效,并且总是会产生Nothing,而不是可能产生默认值。

【讨论】:

  • 是的。但是,请参阅“明显的解决方法(不算作答案)”的第 3 点。
  • 糟糕。我猜要快速阅读问题:(
  • 我更新了我的答案,加入了另一种虽然丑陋的解决方案,但它有点符合您的标准。
【解决方案3】:

System.DBNull.Value 很可能是您所追求的。

扩展,来自 Tech Republic:

...以下 C# 代码确定字符串值是否为空:

string sTest = "Test"; if (sTest == null) { Console.WriteLine("sTest is Null"); }

这段代码在使用 C# 时没有任何问题,但在 VB.NET 中没有 null 关键字的等效项。相反,VB.NET 使用 Nothing 关键字。下面的代码演示了它的用法:

Dim sTest As String
If (sTest Is Nothing) Then
    Console.WriteLine("sTest is Null") 
End If

另一个令人困惑的领域是 VB.NET 不将 null 和 Nothing 视为相等的事实。因此,VB.NET 程序员可能必须检查这两个值。

支持的变化可能会导致混淆,但开发人员很少同时使用两种语言进行开发。另一方面,Microsoft 提供了一种处理空值的统一方法:基本的System.Convert 命名空间包括DBNull 对象。

DBNull

使用DBNull 类表示缺少已知值。 虽然微软文档说它通常在数据库中 应用程序,您也可以将其用于任何类型的数据。

If (sTest.Equals(System.DBNull.Value) Then
    Console.WriteLine("sTest is Null")
End  If 

-- 逐字逐句来自Working with Null values in the .NET Framework

【讨论】:

  • System.DBNull.Value IsNot Nothing.
【解决方案4】:

您可以自己创建一个(如果您愿意,可以为函数选择不同的名称):

Private Function ValueOrNull(expression As Boolean, value As Object) As Object
  If expression Then Return value
  Return Nothing
End Function

用法:

Dim myBool As Boolean
Dim o As Object = ValueOrNull(myBool, 5)

适用于任何类型,包括您使用 5.0 的示例。

【讨论】:

    猜你喜欢
    • 2014-02-11
    • 2020-06-23
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 2015-10-10
    • 2011-04-13
    • 2013-09-14
    相关资源
    最近更新 更多