编译器值类型解析和硬编码“0"整数值

Compiler Value Type Resolution and Hardcoded quot;0quot; Integer Values(编译器值类型解析和硬编码“0整数值)

本文介绍了编译器值类型解析和硬编码“0"整数值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,一些背景知识.阅读问题并接受答案张贴在这里 针对我的问题的特定场景.我不确定是否存在其他类似的案例,但这是我知道的唯一案例.

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 is the only case I am aware of.

上面的怪癖"是我很早就意识到的.直到最近我才完全了解原因.

The above "quirk" is something that I've been aware of for a long time. I didn't understand the full breadth of the cause until just recently.

Microsoft 关于 SqlParameter 类的文档更清楚地说明了这种情况.

Microsoft's documentation on the SqlParameter class sheds a little more light on the situation.

在 value 参数中指定 Object 时,SqlDbType 为从 Object 的 Microsoft .NET Framework 类型推断.

When you specify an Object in the value parameter, the SqlDbType is inferred from the Microsoft .NET Framework type of the Object.

在使用 SqlParameter 构造函数的这种重载时要小心指定整数参数值.因为这个重载需要一个Object 类型的值,您必须将整数值转换为 Object键入值为零时,如以下 C# 示例所示.

Use caution when you use this overload of the SqlParameter constructor to specify integer parameter values. Because this overload takes a value of type Object, you must convert the integral value to an Object type when the value is zero, as the following C# example demonstrates.

Parameter = new SqlParameter("@pname", Convert.ToInt32(0));

如果你这样做不执行此转换,编译器假定您正在尝试调用SqlParameter(string, SqlDbType) 构造函数重载.

If you do not perform this conversion, the compiler assumes that you are trying to call the SqlParameter (string, SqlDbType) constructor overload.

(强调.添加)

我的问题是为什么编译器假定当您指定硬编码0"(并且只有值0")时,您试图指定枚举类型,而不是整数类型?在这种情况下,它假定您声明的是 SqlDbType 值,而不是值 0.

My question is why does the compiler assume that when you specify a hard coded "0" (and only the value "0") that you are trying to specify an enumeration type, rather than an integer type? In this case, it assumes that you are declaring SqlDbType value, instead of the value 0.

这是不直观的,更糟糕​​的是,错误是不一致的.我有我编写的旧应用程序多年来一直调用存储过程.我将对应用程序进行更改(通常甚至与我的 SQL Server 类无关),发布更新,而这个问题会突然破坏应用程序.

This is non-intuitive and, to make matters worse, the error is inconsistent. I have old applications that I've written which have called stored procedures for years. I'll make a change to the application (often times not even associated with my SQL Server classes), publish an update, and this issue will all of a sudden break the application.

当一个包含多个方法签名的对象包含两个相似的签名,其中一个参数是对象/整数而另一个接受枚举时,为什么编译器会被值 0 混淆?

正如我所提到的,我从未将这视为任何其他类的任何其他构造函数或方法的问题.这是 SqlParameter 类独有的还是 C#/.Net 中继承的错误?

As I've mentioned, I've never seen this as a problem with any other constructor or method on any other class. Is this unique to the SqlParameter class or is this a bug inherit within C#/.Net?

推荐答案

这是因为零整数可以隐式转换为枚举:

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)

(改编自 Visual C# 2008 重大更改 - 更改 12)

当编译器执行重载决议时,0 是 适用的函数成员 对于 SqlDbTypeobject 构造函数,因为:

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

存在从实参类型到相应形参类型的隐式转换(第 6.1 节)

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

(SqlDbType x = 0object x = 0 都有效)

SqlDbType 参数优于 object 参数,因为 更好的转换规则:

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

  • 如果 T1T2 是同一类型,则两种转换都不是更好.
    • objectSqlDbType 不是同一个类型
    • If T1 and T2 are the same type, neither conversion is better.
      • object and SqlDbType are not the same type
      • 0 不是 object
      • 0 不是 SqlDbType
      • 不存在从 objectSqlDbType 的隐式转换
      • No implicit conversion from object to SqlDbType exists
      • 存在从SqlDbTypeobject的隐式转换,所以SqlDbType是更好的转换
      • An implicit conversion from SqlDbType to object exists, so the SqlDbType is the better conversion

      请注意,确切构成常量 0 的内容在 Visual C# 2008(微软对 C# 规范的实现)正如@Eric 在他的回答中所解释的那样.

      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.

      这篇关于编译器值类型解析和硬编码“0"整数值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:编译器值类型解析和硬编码“0"整数值