Ale*_*191 5 c# type-conversion implicit-conversion
为什么是一个明确的转换,从double以Foo可能的,即使Foo只从定义明确的转换int来Foo?
为什么在我的情况下double隐式转换为int?
using System;
class Program
{
static void Main(string[] args)
{
double doub = 15.7;
Foo foo = (Foo)doub;
Console.WriteLine(foo.value); //writes "15"
}
}
struct Foo
{
public int value;
public static explicit operator Foo(int val) //no matter if implicit
{
return new Foo { value = val };
}
}
Run Code Online (Sandbox Code Playgroud)
我相信这是在C#5语言规范的第6.4.3节中列出的.
6.2.8用户定义的显式转换(强调我的)中给出了第一个提示:
用户定义的显式转换包括可选的标准显式转换,然后执行用户定义的隐式或显式转换运算符,然后是另一个可选的标准显式转换
请注意,不会发生一次但可能发生三次转换.
现在,要了解什么是"标准显式转换",我们必须查看部分6.2.3 Standard explicit conversions:
标准显式转换是标准隐式转换以及存在相反标准隐式转换的显式转换的子集.换句话说,如果从类型A到类型B存在标准隐式转换,则存在标准显式转换,从类型A到类型B,从类型B到类型A.
回顾一下6.3.1 Standard implicit conversions我们可以看到这是它的一部分:
- 隐式数字转换(第6.1.2节)
换句话说:double -> int可以在用户定义的转换之前应用显式数字转换(如).
如果我们现在看一下,6.4.3 Evaluation of user-defined conversions我们会看到以下内容(强调我的):
首先,如果需要,执行从源类型到用户定义或提升转换运算符的操作数类型的标准转换
接下来,调用用户定义或提升的转换运算符以执行转换.
最后,如果需要,执行从用户定义或提升的转换运算符的结果类型到目标类型的标准转换.
这正是您的方案中发生的情况.
C# 规范的相关部分是
本节很长,但摘要如下:您正在使用 定义显式转换(Foo)doub,并且由于您使用的是显式转换,编译器将选择最具体的可用转换,包括仅显式的转换,以完成中间步骤沿着转换路径(如果可用)。
如果 U 恰好包含一个从 SX 转换为 TX 的用户定义转换运算符,则这是最具体的转换运算符。如果不存在这样的运算符,或者存在多个这样的运算符,则转换将不明确并且会发生编译时错误。否则,将应用用户定义的转换:
如果 S 不是 SX,则执行从 S 到 SX 的标准显式转换。
调用最具体的用户定义的转换运算符来从 SX 转换为 TX。
如果 TX 不是 T,则执行从 TX 到 T 的标准显式转换。
(强调我的)
这里S是源类型,T是目标类型,而SX是在目标类型(即;Foo)的显式运算符中定义的最具体的源类型,TX是在 的显式运算符中定义的最具体的目标类型T。
double这里存在从到 的显式转换int,因此选择最合适的方式从源参数类型 ( double -- S) 转换为显式运算符的输入参数类型 ( int -- SX)。它不需要是明确的,因为您已经明确地将转换为Foo.
这只有效,因为没有模棱两可的替代方案。如果您定义Foo有:
struct Foo
{
public int value;
public uint uvalue;
public static explicit operator Foo(int val)
{
return new Foo { value = val };
}
public static explicit operator Foo(uint val)
{
return new Foo { uvalue = val };
}
}
Run Code Online (Sandbox Code Playgroud)
例如,这会产生以下编译时错误(具有相同的Main):
错误 1 从“double”转换为“Foo”时,用户定义的转换“Foo.explicit operator Foo(uint)”和“Foo.explicit operator Foo(int)”不明确
同样,这是按书本规定的(根据上面引用的第一段),因为可用转换集U现在包含两个同样有效的显式转换,并且编译器无法决定您是否打算调用转换int或转换uint。在最初的例子中只有一次选择,而且很清楚,所以编译器会接受它。
| 归档时间: |
|
| 查看次数: |
400 次 |
| 最近记录: |