Unintuitive behaviour with struct initialization and default arguments

后端 未结 5 1709
半阙折子戏
半阙折子戏 2021-02-12 17:46
public struct Test 
{
    public double Val;
    public Test(double val = double.NaN) { Val = val; }
    public bool IsValid { get { return !double.IsNaN(Val); } }
}

Te         


        
5条回答
  •  离开以前
    2021-02-12 18:31

    In C# (at least until C# 6 - see blog post), invoking new Test() is equivalent to writing default(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 checks that optional arguments do not conflict with already existing overloads is unaware of a possible conflict with the initializer in the case of structs;
    • 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:

        It is true that the compiler implementation has so far "optimized" 'new T()' to mean essentially default(T) when T is a struct. That was actually a bug - it was always supposed to call an actual parameterless constructor if there is one - which there could have been all along, since it is allowed in IL.

        For your example, it means that new Test() is effectively replaced by the compiler to default(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.

提交回复
热议问题