Reputation: 108957
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
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
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
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 nop
s, ret
s 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
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
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
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