泛型的默认值

18

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

T variable = default(T);
  1. 我该如何在VB中完成这个操作?
  2. 如果这只返回null(C#)或nothing(vb),那么值类型会发生什么?
  3. 有没有一种方法可以为自定义类型指定默认值?例如,如果我希望默认值相当于调用我的类上的无参数构造函数。
3个回答

23

问题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: 对于值类型,结构的所有成员都将被“清空”,即所有引用类型成员都设置为nullNothing),所有值类型依次被置空。因此,否定了其他答案中建议字符串会产生""的说法,因为string是一个引用类型。
问题3: 不,没有办法指定这个。已经有一些关于此的线程在Stack Overflow上,例如这里。Jon在这里发表了一篇优秀的解释。

1
除非你在泛型参数上指定了这个约束,否则T()是不准确的。 - Micah
2
Micah:是的,我已经提到过了:约束中必须指定NewStructure之一。 - Konrad Rudolph
1
轻微更正 - 默认构造函数不会被调用。通常这并不重要,因为在IL中你只能为值类型定义一个无参数的构造函数 - 但是它不会被默认(T)调用。 - Jon Skeet
@Jon:我是否已经提到过,我讨厌每个程序员都发明他们自己的术语?为什么他们非要为 .NET 发明自己的术语呢?用 C++ 建立的术语描述这里正在发生的事情是完全准确的,那出了什么问题呢?......不管怎样,感谢你的纠正。 - Konrad Rudolph
如果TNew约束并且在运行时恰好是引用类型,那么Dim variable As New T()肯定会做一些其他的事情(即创建一个实例并返回对它的引用),而不是第一个(返回Nothing)。此外,在2015年将会推出VB.NET的新版本,其中值类型可以具有无参数实例构造函数,这也将改变这些值类型的情况。 - Jeppe Stig Nielsen
@Jeppe 是的,它做了其他的事情。不知道为什么我在这里列出它。 - Konrad Rudolph

6
事实上,正确的方法是将“null”(“Nothing”)类型强制转换为您的泛型类型,如下所示:

Dim tmpObj As T = CType(Nothing, T)

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

0

作为一个不是VB的人,我在最初的回答中犯了一些错误,而Konrad纠正了我的错误。原始答案如下,但我想根据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

原始(错误)答案

看起来VB没有default(T)的等价物。 然而根据this post所述,在VB中,与C#不同,如果T是值类型,则您仍然可以使用Nothing,在大多数情况下在语义上是相同的。

您需要注意的一个重要问题是,如果您需要在代码内部测试它,那么在通常使用default(T)的情况下,您将无法使用Nothing。请考虑以下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 在任何语言中的行为都完全相同,但是在 C# 版本中,DoSomething 将打印 "x is default.",而在 VB 版本中将打印 "x has a value."。

不,这是不正确的。对于值类型,default(T)Nothing是*完全相同的。此外,您的代码翻译是不正确的,相关的VB代码应该写成x = Nothing,这样可以很好地工作。Is等价于C#的object.ReferenceEquals - Konrad Rudolph
谢谢你纠正我。我会更新我的答案以反映这一点。 - Jon Norton

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