public struct Test
{
public double Val;
public Test(double val = double.NaN) { Val = val; }
public bool IsValid { get { return !double.IsNaN(Val); } }
}
Test myTest = new Test();
bool valid = myTest.IsValid;
The above gives valid==true
because the constructor with default arg is NOT called and the object is created with the standard default val = 0.0.
If the struct is a class the behaviour is valid==false
which is what I would expect.
I find this difference in behaviour and particularly the behaviour in the struct case suprising and unintuitive - what is going on? What does the default arg on the stuct construct serve? If its useless why let this compile?
Update: To clarify the focus here is not on what the behaviour is - but rather why does this compile without warning and behave unintuitively. I.e If the default arg is not applied because in the new Test() case the constructor is not called then why let it compile?
In C# (at least until C# 6 - see blog post), invoking
new Test()
is equivalent to writingdefault(Test)
- no constructor is actually called, the default value is provided.The default arg serves no purpose, what happens is that it is likely the result of an oversight in the implementation of the compiler, due to the fact that optional arguments were only added in C# 4:
The code that translates what
new Test()
means is probably unaware of the existence of optional arguments;After digging into comments, I noticed the following gem by Mads Torgersen:
For your example, it means that
new Test()
is effectively replaced by the compiler todefault(Test)
- so that is a bug, which will be fixed in the next version of Visual Studio.In other words, you have a corner case. That would probably be a good time to look at how that behaves in the next version of Visual Studio, as that behavior is changing.