C#与VB.NET - 空结构的处理方式

23

我看到这个问题,想知道为什么在VB.NET中这个代码可以运行成功,而在C#中应该会失败。

//The C# Version

struct Person {
    public string name;
}
...
Person someone = null; //Nope! Can't do that!!
Person? someoneElse = null; //No problem, just like expected

但是在VB.NET中...

Structure Person
    Public name As String
End Structure
...
Dim someone As Person = Nothing 'Wha? this is okay?

“Nothing”和“null”是不同的,它们在处理相同情况时采用了不同的方式,这是否意味着两种语言之间存在差异?
为什么或者说哪些方面的处理不同,导致了一种语言中可以使用这个值,而另一种语言中却不能?
【更新】
鉴于一些评论,我进一步尝试了一下……似乎在VB.NET中,如果你想允许某些东西为空,你实际上必须使用Nullable……例如:
'This is false - It is still a person'
Dim someone As Person = Nothing
Dim isSomeoneNull As Boolean = someone.Equals(Nothing) 'false'

'This is true - the result is actually nullable now'
Dim someoneElse As Nullable(Of Person) = Nothing
Dim isSomeoneElseNull As Boolean = someoneElse.Equals(Nothing) 'true'

太奇怪了...


我在将一些VB.NET移植到C#时偶然发现了这个问题 - 这让我更加讨厌VB.NET ;)。感谢您的深入挖掘,也感谢那些回答的人。 - Charles
请参见https://dev59.com/km025IYBdhLWcg3wqn4N。 - jeroenh
@Charles,我应该因为C#与VB不同而憎恨它吗?有些人解决问题,有些人责怪语言不同。 - Dima
5个回答

30

如果我没记错的话,VB中的'Nothing'表示“默认值”。对于值类型来说,那就是默认值,对于引用类型来说,就是null。因此,将nothing赋给一个结构体是没有问题的。


12

Nothing 在相关类型上大致相当于 default(T)。(刚刚检查过,这也适用于字符串 - 即在字符串上下文中,Nothing 是一个空引用。)


2
是的,但我最后检查时,空字符串也是Nothing。无论是IsNothing("")还是"" Is Nothing都会返回True。也许两者都是。如果不是这两者都是,那么这种差异是可怕的。 - user315772

1

我试图在 MSDN 上搜索,但是在 VB 端找不到任何相关的内容。当在 C# 上搜索 "struct" 时,它清楚地返回它是一个值类型,并且不能被赋予 null 值,因为...它是一个值。

然而,在查看 VB.NET 关键字 "Structure" 时,它没有说明 "Value Type"。相反,它说:

Structure 语句定义了一个复合值类型,您可以对其进行自定义。

那么...是对象吗?

这是我的猜测。我想要找到有关此行为的参考资料,但却找不到。


不,对象应该是 Class,默认为 null。结构体是一种复杂的值类型,可以由多个值甚至方法组成。与 Class 的实际区别在于,Structure 是用实际实例初始化的。使用 Nothing 初始化它只是指定它应该设置为其默认值,这个默认值不是 null(或者我们通常在 VB 中说的 Nothing)。 - awe

0
此外,结构体是值类型(类似于int、char等),因此不可为空。

使用 Nullable 或 ?(C#),您可以使结构体为空。这就是为什么我在不使用 Nullable 的情况下在 VB.NET 中工作时感到如此震惊的原因。 - hugoware
1
@HBoss:使用可空类型,你可以使任何东西为空!甚至是一个 Integer。 我对 BFree 的答案感到惊讶,幸运的是它回答了我的问题,这也导致我看到了这篇文章:如何使用默认值初始化结构体... ;) - awe

-1

因为结构体可能由多种不同类型组成(不是单一值类型,而是可能由多种不同类型组合而成),询问它是否为“Nothing”会破坏使用“Nothing”的逻辑。根据您测试的类型,Nothing的测试结果会有所不同,因此复杂类型不符合使用“Nothing”的逻辑。然而,对于这种类型的测试,即具有其各个组件成员均为其各自的“Nothing”值的结构体,我们使用函数“IsNothing”。例如:

Public Class Employees
    Public Structure EmployeeInfoType
       Dim Name As String    ' String
       Dim Age as Integer    ' Integer
       Dim Salary as Single  ' Single
    End Structure

    Private MyEmp as New EmployeeInfoType

    Public Function IsEmployeeNothing(Employee As EmployeeInfoType) As Boolean
       If **IsNothing**(Employee) Then
          Return True
       Else
          Return False
       End If
    End Function
End Class

IsNothing(Employee) 永远不会评估为“true”,因为该类型不可为空。 - Bernoulli Lizard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接