18

How do I create the default for a generic in VB? in C# I can call:

T variable = default(T);
  1. How do I do this in VB?
  2. If this just returns null (C#) or nothing (vb) then what happens to value types?
  3. Is there a way to specify for a custom type what the default value is? For instance what if I want the default value to be the equivalent to calling a parameterless constructor on my class.
Dillie-O
  • 29,277
  • 14
  • 101
  • 140
Micah
  • 111,873
  • 86
  • 233
  • 325

3 Answers3

23

Question 1:

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

Notice that the latter only works if you specify the Structure constraint for the generic type (for reference types, New T() in VB does something else than default(T) in C#).

Question 2:

For value types all members of the struct are “nulled” out, i.e. all reference type members are set to null (Nothing) and all value types are in turn nulled out.

And no, since string is a reference type, it does not result in "" for strings as suggested in the other answer.

Question 3:

No, there's no way to specify this. There are some threads about this on Stack Overflow already, e.g. here. Jon has posted an excellent explanation why this is.

Community
  • 1
  • 1
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 1
    the New T() is not accurate unless you have that constraint specified on the generic parameter. – Micah Dec 09 '08 at 20:40
  • 2
    Micah: Yes, I had mentioned that already: either `New` or `Structure` must be specified in the constraint. – Konrad Rudolph Dec 09 '08 at 20:43
  • 1
    Slight correction - the default constructor *isn't* invoked. It normally doesn't make a difference because you can only define a parameterless constructor for a value type in IL - but it isn't called for default(T). – Jon Skeet Dec 09 '08 at 20:59
  • @Jon: Did I already mention how I hate the fact that every programmer invents their own terminology? Why the hell did they have to invent their own for .NET? What was wrong with the one established by C++ that describes perfectly well what's happening here? … But anyway, thanks for the correction. – Konrad Rudolph Dec 09 '08 at 21:01
  • In the case where `T` has the `New` constraint and happens to be a reference type at run-time, surely `Dim variable As New T()` does something else (namely creates an instance and returns the reference to it) than the first one (which returns `Nothing`). Additionally, in 2015 there will come a new version of VB.NET in which value types can have parameterless instance constructors, so that will change things for these value types as well. – Jeppe Stig Nielsen Dec 22 '14 at 09:20
  • @Jeppe Yes, it does something else. No idea why I listed it here. – Konrad Rudolph Dec 22 '14 at 10:27
6

Actually folks the correct way of doing this is to cast the null (Nothing) type as your generic type as follows:

Dim tmpObj As T = CType(Nothing, T)

If you want to return the default value for the generic you simply return CType(Nothing, T)

user234662
  • 69
  • 1
  • 1
0

Not really being a VB guy, I made some mistakes in my original answer that Konrad set me straight on. The original answer is below, but I wanted to update my answer to be correct based on Konrad's input.

As Konrad says, default(T) and Nothing are in fact equivalent for both value and reference types. The correct VB code should be as follows in which case you would get the exact same behavior you get in my C# code:

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

Original (WRONG) Answer

It looks like there is no VB equivalent to default(T). However according to this post, unlike in C#, if T is a value-type, in VB you can still use Nothing which is semantically the same in most cases.

The big place where you would have a problem using Nothing where you would normally use default(T) is if you need to test for it inside your code. Consider the following C# code:

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.");
}

Translated to VB like this:

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

If T is a reference type, both versions will act exactly the same for both ReturnSomething and DoSomething. However, if T is a value type, ReturnSomething will act exactly the same for either language, but DoSomething will print "x is default." in the C# version, but "x has a value." in the VB version.

Jon Norton
  • 2,969
  • 21
  • 20
  • No, this is not correct. For value types, `default(T)` and `Nothing` are *exactly* the same. Also, your code translation is incorrect, the relevant VB code should read `x = Nothing` which works very well. `Is` is equivalent to C#'s `object.ReferenceEquals`. – Konrad Rudolph Dec 09 '08 at 21:22
  • Thanks for setting me straight. I'll update my answer to reflect this. – Jon Norton Dec 10 '08 at 13:24