gpt4 book ai didi

c# - 编译器值类型解析和硬编码 "0"整数值

转载 作者:IT王子 更新时间:2023-10-29 04:47:10 24 4
gpt4 key购买 nike

首先,介绍一下背景。阅读问题并接受答案 posted here对于我的问题的特定场景。我不确定是否存在其他类似案例,但这是我所知道的唯一案例。

上面的“怪癖”是我早就知道的事情。直到最近,我才明白其中的全部原因。

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

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

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));

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。

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

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

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

最佳答案

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

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 Breaking Changes - change 12)

当编译器执行重载决议时 0 是一个 Applicable function member对于 SqlDbTypeobject 构造函数,因为:

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 参数,因为 better conversion rules :

  • 如果 T1T2 是同一类型,则两种转换都不是更好。
    • objectSqlDbType 不是同一类型
  • 如果 ST1,则 C1 是更好的转换。
    • 0 不是对象
  • 如果 ST2,则 C2 是更好的转换。
    • 0 不是 SqlDbType
  • 如果存在从T1T2的隐式转换,并且不存在从T2T1的隐式转换, C1 是更好的转换。
    • 不存在从objectSqlDbType 的隐式转换
  • 如果存在从T2T1的隐式转换,并且不存在从T1T2的隐式转换, C2 是更好的转换。
    • 存在从 SqlDbTypeobject 的隐式转换,因此 SqlDbType 是更好的转换

请注意,在 Visual C# 2008确切地构成常量 0 的内容已经(非常微妙地)发生了变化(微软对 C# 规范的实现)@Eric 在他的回答中解释道。

关于c# - 编译器值类型解析和硬编码 "0"整数值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14224465/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com