【问题标题】:Default value for generics泛型的默认值
【发布时间】:2008-12-09 20:32:41
【问题描述】:

如何在 VB 中为泛型创建默认值?在 C# 中我可以调用:

T variable = default(T);
  1. 如何在 VB 中做到这一点?
  2. 如果这只是返回 null (C#) 或什么都不返回 (vb),那么值类型会发生什么?
  3. 有没有办法为自定义类型指定默认值?例如,如果我希望默认值等同于在我的类上调用无参数构造函数。

【问题讨论】:

    标签: c# .net vb.net generics


    【解决方案1】:

    问题一:

    Dim variable As T
    ' or '
    Dim variable As T = Nothing
    ' or '
    Dim variable As New T()
    

    请注意,后者仅在您为泛型类型指定 Structure 约束时才有效(对于引用类型,VB 中的 New T() 与 C# 中的 default(T) 不同)。

    问题2:

    对于值类型,结构的所有成员都被“清空”,即所有引用类型成员都设置为null (Nothing),而所有值类型又被清空。

    不,因为string 是一个引用类型,它确实不导致"" 用于其他答案中建议的字符串。

    问题3:

    不,没有办法指定这一点。 Stack Overflow 上已经有一些关于此的主题,例如here。 Jon 发布了一个 excellent explanation 这是为什么。

    【讨论】:

    • New T() 是不准确的,除非您在泛型参数上指定了该约束。
    • Micah:是的,我已经提到过:New 或 Structure 必须在约束中指定。
    • 轻微修正 - 默认构造函数没有被调用。它通常不会产生影响,因为您只能在 IL 中为值类型定义无参数构造函数 - 但不会为 default(T) 调用它。
    • @Jon:我是否已经提到我讨厌每个程序员都发明自己的术语这一事实?为什么他们必须为 .NET 发明自己的东西? C++ 建立的完美描述这里发生的事情的错误是什么? …但无论如何,感谢您的更正。
    • 如果T 具有New 约束并且在运行时恰好是引用类型,那么Dim variable As New T() 肯定会做其他事情(即创建一个实例并将引用返回到它)比第一个(返回Nothing)。此外,2015 年将出现一个新版本的 VB.NET,其中值类型可以具有无参数的实例构造函数,因此这些值类型也会发生变化。
    【解决方案2】:

    实际上,人们这样做的正确方法是将null (Nothing) 类型转换为您的泛型类型,如下所示:

    Dim tmpObj As T = CType(Nothing, T)
    

    如果要返回泛型的默认值,只需返回 CType(Nothing, T)

    【讨论】:

      【解决方案3】:

      不是真正的 VB 人,我在最初的答案中犯了一些错误,康拉德让我直截了当。原始答案如下,但我想根据 Konrad 的输入更新我的答案以使其正确。

      正如 Konrad 所说,default(T) 和 Nothing 实际上对于值类型和引用类型都是等价的。正确的 VB 代码应如下所示,在这种情况下,您将获得与我的 C# 代码完全相同的行为:

      Function ReturnSomething(Of T)() As T
          Return Nothing
      End Function
      
      Function DoSomething(Of T)()
          Dim x as T = Nothing;
          If x = Nothing Then
              Console.WriteLine("x is default.")
          Else
              Console.WriteLine("x has a value.")
          End If
      

      原始(错误)答案

      似乎没有与default(T) 等效的VB。但是根据this post,与C#不同,如果T是值类型,在VB中你仍然可以使用Nothing,这在大多数情况下语义相同。

      您在使用Nothing 而通常使用default(T) 时遇到问题的大地方是您是否需要在代码中对其进行测试。考虑以下 C# 代码:

      T ReturnSomething<T>()
      {
          return default(T);
      }
      
      void DoSomething<T>()
      {
          T x = default(T);
          if(x == default(T))
              Console.WriteLine("x is default.");
          else
              Console.WriteLine("x has a value.");
      }
      

      这样翻译成VB:

      Function ReturnSomething(Of T)() As T
          Return Nothing
      End Function
      
      Function DoSomething(Of T)()
          Dim x as T = Nothing;
          If x Is Nothing Then
              Console.WriteLine("x is default.")
          Else
              Console.WriteLine("x has a value.")
          End If
      End Function
      

      如果T 是引用类型,则两个版本对ReturnSomething 和DoSomething 的行为完全相同。然而,如果T 是一个值类型,ReturnSomething 对任何一种语言的行为都完全相同,但DoSomething 将打印“x 是默认值”。在 C# 版本中,但“x 有值”。在VB版本中。

      【讨论】:

      • 不,这是不正确的。对于值类型,default(T) 和 Nothing完全相同相同。另外,您的代码翻译不正确,相关的 VB 代码应为x = Nothing,效果很好。 Is 等价于 C# 的 object.ReferenceEquals。
      • 感谢您直言不讳。我会更新我的答案以反映这一点。
      猜你喜欢
      • 2018-09-12
      • 1970-01-01
      • 2011-02-14
      • 2022-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      相关资源
      最近更新 更多