在VB.NET中,与C#中的 `default` 相当的是什么?

18

我通常使用C#编程,现在需要调查一下VB.NET代码的性能问题——我想要比较某个变量与其类型的默认值(有点像C#中的default关键字)。

public class GenericThing<T1, T2>
{
    public T1 Foo( T2 id )
    {
        if( id != default(T2) ) // There doesn't appear to be an equivalent in VB.NET for this(?)
        {
            // ...
        }
    }
}

我曾相信Nothing与语义相同,但如果我执行以下操作:

Public Class GenericThing(Of T1, T2)
    Public Function Foo( id As T2 ) As T1
        If id IsNot Nothing Then
            ' ...
        End If
    End Function
End Class

T2Integer类型,且id的值为0时,条件仍然满足,if语句的内容将被执行。但是,如果我这样做:

    Public Function Bar( id As Integer ) As T1
        If id <> Nothing Then
            ' ...
        End If
    End Function

那么条件不满足,就不会执行代码块...

1
可能是 VB 中 C# 的 default(T) 的等效项 的重复问题。 - decyclone
2
@decyclone 那个问题并不涵盖一般情况;实际上,在我的问题中,我展示了我知道在大多数情况下如何使用 Nothing... - Rowland Shaw
如果 id.Equals(CType(Nothing, T2)),那么 - Brain2000
3个回答

22

与C#不同,VB.NET不需要使用表达式初始化局部变量。它会在运行时自动初始化为默认值。这就是你可以用来替代default关键字的东西:

    Dim def As T2    '' Get the default value for T2
    If id.Equals(def) Then
       '' etc...
    End If

别忘了添加注释,它会让某些人在一年后感到困惑。


12

这不是一个完整的解决方案,因为您的原始C#代码无法编译。您可以通过一个本地变量使用Nothing:

Public Class GenericThing(Of T)
    Public Sub Foo(id As T)
        Dim defaultValue As T = Nothing
        If id <> defaultValue Then
            Console.WriteLine("Not default")
        Else
            Console.WriteLine("Default")
        End If
    End Function
End Class

这段代码无法编译,与C#版本一样无法编译 - 不能像那样比较未受限制的类型参数的值。

你可以使用EqualityComparer(Of T),这样你甚至不需要局部变量:

If Not EqualityComparer(Of T).Default.Equals(id, Nothing) Then

我认为我在示例中去掉了一些业务特定术语,但这似乎适用于值类型 - 你知道它对引用类型也适用吗? - Rowland Shaw
@Rowland:据我所知,应该没问题。 - Jon Skeet
好的,我正在打字编译,很快就会知道确切情况;我可以看出那会迫使编译器进行魔法操作并让它能够工作。 - Rowland Shaw

5
你代码中的问题在于IsNot运算符,而不是Nothing关键字。根据文档

IsNot运算符用于确定两个对象引用是否指向不同的对象。但它不执行值比较。

你试图使用引用运算符进行值比较。一旦你意识到这一点,Jon Skeet或Hans Passant的答案就成为显而易见的解决方案。


非常有道理 - 我总是感到烦恼的是 VB 在比较时既有 = 号又有 Is,而开发人员需要知道分别比较值类型还是引用类型。 - Rowland Shaw
@Rowland - C# 也有“is”运算符。我使用一个经验法则,适用于C#和VB:首先使用.Equals(),如果编译器报错,则使用== / =,如果编译器仍然报错,则使用is。 - Joel Coehoorn
@Joel/Rowland,习惯让我更喜欢使用=/==来处理对象/类。当使用可空类型(Guid?,DateTime?等)时,我倾向于使用Equals。我经常遇到将Guids不当地(作为字符串)处理而不是Guid?的代码...当我不得不使用is null时,它实际上会更加恼人,因为= null通常会破坏我正在尝试做的事情,特别是在SQL中。 - Tracker1

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