Compiler Value Type Resolution and Hardcoded “0” Integer Values

后端 未结 5 902
野的像风
野的像风 2020-11-28 11:50

First, a bit of background. Read the question and accepted answer posted here for a specific scenario for my question. I\'m not sure if other, similar cases exist but this

5条回答
  •  抹茶落季
    2020-11-28 12:44

    It's because a zero-integer is implicitly convertible to an enum:

    enum SqlDbType
    {
        Zero = 0,
        One = 1
    }
    
    class TestClass
    {
        public TestClass(string s, object o)
        { System.Console.WriteLine("{0} => TestClass(object)", s); } 
    
        public TestClass(string s, SqlDbType e)
        { System.Console.WriteLine("{0} => TestClass(Enum SqlDbType)", s); }
    }
    
    // This is perfectly valid:
    SqlDbType valid = 0;
    // Whilst this is not:
    SqlDbType ohNoYouDont = 1;
    
    var a1 = new TestClass("0", 0);
    // 0 => TestClass(Enum SqlDbType)
    var a2 = new TestClass("1", 1); 
    // => 1 => TestClass(object)
    

    (Adapted from Visual C# 2008 Breaking Changes - change 12)

    When the compiler performs the overload resolution 0 is an Applicable function member for both the SqlDbType and the object constructors because:

    an implicit conversion (Section 6.1) exists from the type of the argument to the type of the corresponding parameter

    (Both SqlDbType x = 0 and object x = 0 are valid)

    The SqlDbType parameter is better than the object parameter because of the better conversion rules:

    • If T1 and T2 are the same type, neither conversion is better.
      • object and SqlDbType are not the same type
    • If S is T1, C1 is the better conversion.
      • 0 is not an object
    • If S is T2, C2 is the better conversion.
      • 0 is not a SqlDbType
    • If an implicit conversion from T1 to T2 exists, and no implicit conversion from T2 to T1 exists, C1 is the better conversion.
      • No implicit conversion from object to SqlDbType exists
    • If an implicit conversion from T2 to T1 exists, and no implicit conversion from T1 to T2 exists, C2 is the better conversion.
      • An implicit conversion from SqlDbType to object exists, so the SqlDbType is the better conversion

    Note that what exactly constitutes a constant 0 has (quite subtly) changed in Visual C# 2008 (Microsoft's implementation of the C# spec) as @Eric explains in his answer.

提交回复
热议问题