【问题标题】:Nothing after a New, is it possible?新之后什么都没有,这可能吗?
【发布时间】:2013-01-22 16:20:18
【问题描述】:

Nothing 在New 之后,有可能吗?

Dim myObj As MyClass = Nothing
myObj = New MyClass(params)
If myObj Is Nothig Then
  ' is it possible?
End If

构造函数返回空(无)对象是否存在理论上的可能性?

说,在构造函数中设置Me = Nothing?或者,如果在构造函数中抛出异常,对象的 catch 中会发生什么? 或者在最后一个构造函数行中,我通过引用“Me”传递给一个方法,而这个方法将该引用设置为 Nothing?

【问题讨论】:

  • 我认为 MyClass 构造函数将抛出异常(如果不处理将停止执行),或者构造函数将返回并将 MyClass 的新实例分配给 myObj。跨度>
  • 不,我认为new 永远不会返回null/nothing
  • @KenPespisa:即使不太可能,VB.NET 的行为也可能与 C# 不同,因此我不会将其称为重复项(请注意,即使 Nothing 和 null 也是相当不同)。

标签: .net vb.net oop


【解决方案1】:

不,New-operator 用于创建新的对象实例。即使这个对象的所有字段都保持Nothing,实例本身也不是Nothing。

Visual Basic Language Specification:

11.10 新表达式 New 运算符用于创建类型的新实例。 ....

11.10.1 对象创建表达式 对象创建表达式用于创建类类型或结构类型的新实例。这 对象创建表达式的类型必须是类类型,a 结构类型,或具有 New 约束且不能 成为 MustInherit 类。给定一个对象创建表达式 形成 New T(A),其中 T 是类类型或结构类型,A 是 可选参数列表,重载决议确定正确的 要调用的 T 的构造函数。具有 New 约束的类型参数是 被认为有一个单一的、无参数的构造函数。 如果没有 构造函数是可调用的,发生编译时错误;否则 表达式导致创建一个新的 T 实例,使用 选择的构造函数。 如果没有参数,括号可能是 省略。分配实例的位置取决于 instance 是类类型或值类型。类类型的新实例 在系统堆上创建,而值类型的新实例是 直接在栈上创建。对象创建表达式可以 可选地在构造函数之后指定成员初始值设定项列表 论据。这些成员初始化器以关键字为前缀 和初始化列表被解释为好像它在 With 语句的上下文。

【讨论】:

  • 是否可以在构造函数中设置 Me = Nothing?或者如果在构造函数中抛出异常,会发生什么?或者如果我通过引用“我”传递给一个方法,而这个方法将该引用设置为 Nothing?
【解决方案2】:

除非你使用On Error Resume Next并且MyClass构造函数中有异常,或者你create a proxy that returns Nothing on creation。

在确认代理的 VB.NET 版本“有效”时,我注意到 myObj Is Nothing 在创建后立即是 False(就像您在 OP 中要求的那样),但是当您尝试做其他事情时有了它,它肯定看起来像Nothing。一旦你尝试用它做更多而不是测试它的价值,它通常会变成Nothing。 (在这个阶段,C#也是如此。在这一点上,我真的应该开始一个新的问题......)

但我发现“空”Try Catch 的存在足以让 VB.NET 将Nothing 结晶! (在 LinqPad 的 Roslyn C# 6(Beta)版本中,C# 的性能相同。)

Sub Main()
    Dim myObj = New MyFunnyType()
    If myObj Is Nothing Then
      Call "It IS Nothing".Dump
    Else
      ' Comment out this Try and myObj will not be Nothing below.
      Try
        'Call myObj.ToString.Dump
      Catch nr As NullReferenceException
        Call "Maybe it was nothing?".Dump
      Catch ex As Exception
        Call ex.Message.Dump
      End Try
      Call myObj.Dump("Nil?")
      If myObj Is Nothing Then
        Call "Now it IS Nothing".Dump
      Else
        Call "It still is NOT Nothing!".Dump
      End If
    End If
End Sub

' Define other methods and classes here
Class MyFunnyProxyAttribute
  Inherits ProxyAttribute
    Public Overrides Function CreateInstance(ByVal ServerType As Type) As MarshalByRefObject
        Return Nothing
    End Function
End Class

<MyFunnyProxy> _
Class MyFunnyType
  Inherits ContextBoundObject
  Public Overrides Function ToString() As String
    If Me IsNot Nothing Then
      Return "Yes, I'm here!"
    Else
      Return "No, I'm really Nothing!"
    End If
  End Function
End Class

请注意,对ToString 的调用是要被注释掉的:如果不是,Nothing 会被具体化为“预期的”。

(在基于 Roslyn C# 6 的 LinqPad 之前,我在 C# 中没有看到类似的效果。即仅在 try 中注释掉 ToString 调用就足以让 myObj 保持非 null . C# 6 LinqPad (Beta) 的性能与 VB.NET 相同,需要删除 try 才能使 null 不结晶。)

【讨论】:

  • 所以,这可能发生在异常之后,或者通过其他方法引用“annulation”......
  • 我没有在答案中提到它,因为我还没有找到确认它的参考,但是,是的,我想我以前见过代理构造函数返回 @987654341 的“有趣”代码@.
  • 找到了!仅来自臭名昭著的What's the strangest corner case you've seen in C# or .NET? 最受好评的答案!
  • 顺便说一句,instance 是在 C# 和 VB.NET 中的“最奇怪的极端案例”答案中的通用方法案例中的 Nothing。
猜你喜欢
  • 1970-01-01
  • 2013-10-03
  • 1970-01-01
  • 1970-01-01
  • 2015-03-02
  • 2016-03-11
  • 1970-01-01
  • 2020-11-19
  • 2011-07-20
相关资源
最近更新 更多