Bala R
Bala R

Reputation: 108957

C# struct new StructType() vs default(StructType)

Say I have a struct

public struct Foo
{
    ...
}

Is there any difference between

Foo foo = new Foo();

and

Foo foo = default(Foo);

?

Upvotes: 59

Views: 17106

Answers (6)

Eric Lippert
Eric Lippert

Reputation: 660159

You might wonder why, if they are exactly the same, there are two ways to do the same thing.

They are not quite the same because every reference type or value type is guaranteed to have a default value but not every reference type is guaranteed to have a parameterless constructor:

static T MakeDefault<T>()
{
    return default(T); // legal
    // return new T(); // illegal
}

UPDATE from 2023: A commenter notes that this answer is out of date; in C# 10, new S() for a struct type S initializes struct fields to their default values, default(S) initializes them to zeros, so there is a difference now. The answer above however still stands; it is not legal to do new T() on a type parameter T unless it is constrained to have a constructor.

Upvotes: 78

Link
Link

Reputation: 1711

Small update with the freshly (C# 10) introduced Parameterless constructors and field initializers. default(MyStruct) and new MyStruct are not the same anymore.

new MyStruct().PrintToConsole();    // Prints 10
default(MyStruct).PrintToConsole(); // Prints 0

public struct MyStruct
{
    private int anyNumber;
    
    public MyStruct()
    {
        anyNumber = 10;
    }
    
    public void PrintToConsole() => System.Console.WriteLine($"My number is: {anyNumber}");
}

If you want to fiddle around on your own here you go

Upvotes: 2

Ani
Ani

Reputation: 113412

For value-types, the options are, practically speaking, equivalent.

However, I was intrigued by Jon Skeet's empirical research into which 'instructions' result in the invocation of a struct's parameterless default constructor when it is specified in CIL (you can't do it in C# because it doesn't let you). Amongst other things, he'd tried out default(T) and new T() where T is a type parameter. They appeared equivalent; neither of them appeared to call the constructor.

But the one case (it appears) he hadn't tried was default(Foo) where Foo is an actual struct type.

So I took his code for the 'hacked' struct and tried that out for myself.


It turns out that default(Foo) doesn't call the constructor, whereas new Foo() in fact does.

Using a struct type Oddity that specifies a parameterless constructor:

With optimizations turned off, the method:

private void CallDefault()
{
    Oddity a = default(Oddity);
}

produces the CIL (without nops, rets etc.):

L_0001: ldloca.s a
L_0003: initobj [Oddity]Oddity

whereas the method:

private void CallNew()
{
    Oddity b = new Oddity();
}

produces:

L_0001: ldloca.s b
L_0003: call instance void [Oddity]Oddity::.ctor()

With optimizations turned on, the compiler appears to optimize away pretty much all of the CallDefault method into a no-op, but keeps the call to the constructor in CallNew (for potential side-effects?).

Upvotes: 14

jason
jason

Reputation: 241651

The language specification (§4.1.2 and §5.2) is your friend. Specifically:

For a variable of a value-type, the default value is the same as the value computed by the value-type’s default constructor (§4.1.2).

(Italics in original.)

Note that this is not the same for reference types.

For a variable of a reference-type, the default value is null.

This is emphatically different than the value produced by a default constructor, if one exists.

Upvotes: 13

Snowbear
Snowbear

Reputation: 17274

default keyword is useful when you do not know exact type and it works not only for structs, for example in generics:

T FirstOrDefault(IEnumerable<T> source)
{
    if (...source is empty...) return default(T);
}

This will return null for reference types, default value for primitive types(0 for numbers, false for bool), defaultly inialized structure, etc ...

When type is known at compile-time it makes no sense to use default, you can use new Foo() instead

Upvotes: 5

Andrew Hare
Andrew Hare

Reputation: 351536

No, both expressions will yield the same exact result.

Since structs cannot contain explicit parameterless constructors (i.e. you cannot define one yourself) the default constructor will give you a version of the struct with all values zero'd out. This is the same behavior that default gives you as well.

Upvotes: 18

Related Questions