【问题标题】:Null(In C#) Vs Nothing(in vb.net)空(在 C# 中)与空(在 vb.net 中)
【发布时间】:2018-12-15 09:33:35
【问题描述】:

C# NULL 与 vb.net Nothing 有何不同?

Console.WriteLine(Nothing = "") => True

Console.WriteLine(null==""); => False

我的理解是nullNothing 是相同的。但上面的代码清楚地解释了它不是。

C#null 在 VB.NET 中的等价物是什么?

【问题讨论】:

  • 这个问题是题外话,因为它会导致意见......
  • @Blackwood 很接近,但它没有回答“VB.NET 中 null 的等价物是什么?”也相关:Nothing vs null。据我所知,VB.NET 没有相当于 C# 的null
  • @Codexer 我不确定这主要是基于意见的,Nothingnull 的含义非常精确。
  • @jrh 如果Nothing 更像default 我希望Nothing = "" 为假,因为string 是一个引用类型,除非它不在VB.Net 中。跨度>
  • Reddy 您是在寻找与 VB.NET 中的 C# 的 null 类似的精确,还是只是在寻找类似于 null 的东西(即Nothing)?请更新您的帖子以澄清,所以这里只有一个问题。

标签: c# vb.net


【解决方案1】:

在您的代码中,VB 猜测您正在比较 Strings,因为其中一个操作数是 String。在String 比较中,Nothing 等价于空的String ""。然后进行值比较,返回True

使用Is 比较参考:

Console.WriteLine(Nothing Is "") '=> False

【讨论】:

  • 虽然你的答案是正确的,但我认为前两句话是不正确的。我不认为 = 运算符除了转换之外什么都不做。如果它们的类型不同,VB 本身会将一个操作数转换为与另一个操作数的类型匹配。 C# 在某些情况下也会这样做,而不是在手头的情况下 (Nothing = ""),但例如,如果一个操作数是 Single 而另一个是 Double。我更新了您的答案以删除前不正确的两行。如果您不同意,可以回滚。
  • @RacilHilan 是的,你是对的。我检查了使用 ILDASM 和 VB = 运算符与 C# == 运算符 (op_Equality) 相同
  • 其实我说的有点太早了。还有一个 IL 函数Microsoft.VisualBasic.CompilerServices.Operators::CompareObjectEqual。 (请参阅msdn.microsoft.com/en-us/library/… 但我认为这已经足够复杂了,您的编辑很好
  • 这会产生一个字符串的默认值,它是一个空字符串“” - 不正确。 String 的默认值为null
  • @Fabio 现在是“挑剔”:)。当然你是对的,因为String 实际上是一个参考。感谢您的评论,我会相应地更新答案。我希望 SSS 可以接受。
【解决方案2】:

您选择了一个小复杂示例来测试 vb.net 中的 Nothing 和 c# 中的 null 之间的区别

来自关于Nothing的Visual basic语言规范:

没有什么是特殊的文字;它没有类型并且是 可转换为类型系统中的所有类型,包括类型 参数。 当转换为特定类型时,它是 相当于该类型的默认值

如果您阅读 Microsoft 文档中对 default value expressions 的描述,您会注意到 vb.net 中的 Nothing 和 C# 中的 default(T) 具有相似的行为。

例如

Dim isSomething As Boolean = Nothing ' = False
Dim amount As Integer = Nothing ' = 0
Dim value As String = Nothing ' = null (notice not empty string!)

证明字符串的默认值不是空字符串,因为这里有很多 cmets/answers

Dim value As String = Nothing
If value.Equals("") Then ' will throw NullReferenceException

End If 

Nothing 与空字符串"""=" 运算符进行比较是vb.net 的特殊情况,因为字符串的Nothing 将评估为null

来自关于 String 类型的关系运算符的 Visual Basic 语言规范:

运算符返回比较两个值的结果 二进制比较或文本比较。使用的比较 由编译环境和Option比较决定 陈述。二进制比较确定数字 Unicode 是否 每个字符串中每个字符的值都相同。文字比较 根据当前使用的文化进行 Unicode 文本比较 .NET 框架。 进行字符串比较时,空引用 相当于字符串文字“”

为了检查 vb.net 中的字符串相等性,您应该使用 String.Equals 方法或 Is 运算符。

基于以上语言规范

我的理解是 null 和 Nothing 都是一样的。但以上 代码清楚地说明它不是。

它们不一样,vb.net中的Nothing相当于C#中的default(T)

C# null 在 VB.NET 中的等价物是什么?

在 C# 中,您不能将 null 设置为值类型,因此对于在 vb.net 中与 C# null 等效的引用类型 (String) 将是 Nothing
例如(null == default(String))

【讨论】:

  • 这个答案清楚地表明 VB 'Nothing' 和 C# 'null' 是不同的概念。这些概念仅在应用于引用类型时是相同的。
  • 这个答案不正确。当您声明变量并且不给它们任何值时,变量的默认值会在 VB 中自动分配。例如,数字类型的默认值为0,布尔型的默认值为false,以此类推。那些的默认值到底是Nothing?这与 C# 不同,C# 不会自动为您初始化变量,如果您在分配值之前尝试使用它们,则会收到警告。阅读接受的答案以获得正确的解释。
  • @RacilHilan, Nothing 任何数据类型的默认值。
  • 好吧,您能否添加一个指向 MSDN 的链接,清楚地表明 Nothing 是 VB 中任何数据类型的默认值?对于我上面的评论,这里是 IntegerBoolean 的 MSDN,请注意备注中所述的默认值。唯一的例外是 String 类型,原因是任何优秀的开发人员都应该知道的。
  • 其实这里有一个MSDN,明确说明了相反的情况:在Visual Basic中,如果你将一个不可为空值类型的变量设置为Nothing,那么这个变量就是设置为其声明类型的默认值。,因此显然Nothing 不是数据类型的默认值(String 除外)。
【解决方案3】:

接受答案的最终版本正确回答了问题。然而,法比奥在他的回答中添加了一些有用的信息,但它有一些不正确的信息和概念。所以这个答案是试图将两个答案合并成一个更完整的答案。

首先,VB 中的Nothing 等同于C# 中的null,因此您对此的理解是正确的,至少部分正确(因为这只是Nothing 关键字的一种用法)。它在整个 MSDN 文献中都有体现,尽管它最近已经淡出并在许多 cmets 中被替换为 null 一词。您的困惑源于 VB 与 C# 不同的行为和特性,以及来自其他语言且没有 VB 经验的程序员对结果感到困惑。

如已接受的答案所述,VB 认为该问题是字符串比较,因为其中一个操作数是字符串。在字符串比较中,VB 将Nothing 视为与MSDN 一样的空字符串""

数值比较将Nothing视为0。字符串比较将Nothing视为“”(空字符串)。

现在,为什么在 VB 中会发生这种情况?这是因为 VB 将 Nothing 关键字用于两个不同的事情(类似于它如何将= 运算符用于两个不同的事情,赋值和比较)。第一种用法相当于我上面提到的 C# 中的null。第二种用法相当于 C# 中的default(T) 运算符。与= 运算符一样,VB 根据上下文知道使用Nothing 的方式。例子:

在这一行中,VB 使用Nothing 作为null

Console.WriteLine(s Is Nothing) //C#: (s == null)

在这些行中,VB 使用Nothing 作为default(T) 为变量分配默认值:

Dim s As String = Nothing //C#: string s = default(string);
Dim i As Integer = Nothing //C#: int i = default(int);

最后,在比较不同类型的变量时,VB 和 C# 都会转换一个操作数以匹配另一个操作数的类型。例如,如果您比较双精度值和整数值。对于这一行,VB 和 C# 都会返回 true

Console.WriteLine(5.0 = 5) //C#: (5.0 == 5)

但是,VB 和 C# 的不同之处在于可以将什么类型转换为什么类型。此外,空字符串 ""null 在 VB 中的字符串比较中被视为相同,但在 C# 中则不同。在大多数情况下,这使事情变得更容易,这在 VB 中是众所周知的。所以你可以很容易地测试你的字符串是否没有这样的值:

Console.WriteLine(s = Nothing)
Console.WriteLine(s = "")

这两行将返回相同的结果,因为 VB 将Nothing 视为"" 进行比较。在 C# 中,你不能这样做,你必须像这样测试两者:

Console.WriteLine(s == null && s == "")

显然,在这种情况下,VB 比最常见的 C# 更简单、更短。然而,这是以失去一些控制为代价的。在您只想测试空引用的不太常见的情况下,C# 显然变得更好,因为您仍然可以使用 == 运算符:

Console.WriteLine(s == null)

在 VB 中,您不能使用 = 运算符,而必须使用另一个 Is 运算符:

Console.WriteLine(s Is Nothing)

此外,虽然 VB 在前一点更容易,但 C# 更清晰。这就是为什么从代码清晰的角度来看,这行代码可以在两种语言中使用,但结果相同:

Console.WriteLine(string.IsNullOrEmpty(s))

【讨论】:

  • 我不确定Default(T) 位。如果您反汇编Dim s As String = Nothing,则发出的IL 将s 设置为您所期望的空引用(ldnullstloc.0)。仅在比较时通过Microsoft.VisualBasic.CompilerServices.Operators::CompareObjectEqual 将其转换为空字符串。
  • @SSS 是的,Nothing 和空字符串"" 的字符串比较是VB 中的一种特殊情况,与default(T) 无关。在这样的比较中,Nothing 实际上就像null。因此,您在最终状态下的回答是对问题的良好回答。我只想添加一些关于 VB 中其他特殊情况的有用信息,例如在分配和自动转换期间将Nothing 视为default(T),这使人们误以为Nothing 不是null。事实上它是nulldefault(T) 行为是次要用法。
【解决方案4】:

Nothing 在 VB 中因对象类型而异: - 引用类型等同于 null - 值类型等同于默认值;可空类型为空

【讨论】:

    猜你喜欢
    • 2010-11-21
    • 2011-07-18
    • 2016-03-15
    • 2011-02-06
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    • 2023-04-06
    • 1970-01-01
    相关资源
    最近更新 更多