Tim*_*mwi 16 c# implicit-conversion
请考虑以下代码:
class Program
{
public static explicit operator long(Program x) { return 47; }
static int Main(string[] args)
{
var x = new Program();
Console.WriteLine((decimal) x);
}
}
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,这个输出47; 换句话说,explicit operator long即使是演员也是如此decimal.
C#规范中是否有明确说明应该发生这种情况(如果是这样,究竟在哪里)或者这是否是我遗漏的其他一些规则的结果?
我能想到的唯一解释是编译器足够聪明,可以实现有一个隐式运算符,它将long转换为十进制,当Program只能转换为long时,它可以用来满足Program和decimal之间的显式转换.
编辑:我们在这里; 数字类型之间的转换内置于语言规范中:
6.1.2隐式数字转换
隐式数字转换是:
·从sbyte到short,int,long,float,double或decimal.
·从byte到short,ushort,int,uint,long,ulong,float,double或decimal.
·从short到int,long,float,double或decimal.
·从ushort到int,uint,long,ulong,float,double或decimal.
·从int到long,float,double或decimal.
·从uint到long,ulong,float,double或decimal.
· 从long到float,double或decimal.
·从ulong到float,double或decimal.
·从char到ushort,int,uint,long,ulong,float,double或decimal.
·从浮动到双重.
从int,uint,long或ulong到float以及从long或ulong到double的转换可能会导致精度损失,但绝不会导致数量级的损失.其他隐式数字转换永远不会丢失任何信息.
char类型没有隐式转换,因此其他整数类型的值不会自动转换为char类型.
因此,在程序和十进制之间进行转换时,C#知道它可以隐式地从任何数字类型转换为十进制,因此在执行此显式转换时,它将查找可以将程序转换为数字类型的任何运算符.
有趣的是,如果您还将显式转换为uint,那么会返回48会发生什么?编译器选哪一个?
我找到了答案.首先,有一种类型的概念被另一种类型所包含,在6.4.3用户定义的转换评估中定义如下:
如果从类型A到类型B存在标准隐式转换(第6.3.1节),并且如果A和B都不是接口类型,那么A被认为包含在 B中,并且B被认为包含 A.
6.3.1标准的隐式转换指出,"隐式数字转换(§6.1.2)"是一种标准的隐式转换,和6.1.2隐数值转换反过来定义了从隐式转换long到decimal.因此,long在所涵盖 decimal.
接下来,6.4.5用户定义的显式转换表明确定显式转换是否适用的其中一个阶段是:
查找适用的用户定义和提升转换运算符集合U.此集合包含由D中的类或结构声明的用户定义和提升的隐式或显式转换运算符,这些运算符从包含或包含在S中的类型转换为T包含或包含T.如果U为空,则转换未定义,并发生编译时错误.
这里,D指的是较早步骤的结果,在这种情况下,仅包含decimal,Program和object.因此,该集U将包含我声明的Program-to- longexplicit运算符,因为long它包含在decimal(如前所述).
接下来的步骤之一选择long作为最具体的目标类型, TX.
最后,同一算法的最后一步说明:
最后,应用转换:
- 如果S不是SX,则执行从S到SX的标准显式转换.
- 调用最具体的用户定义转换运算符以从SX转换为TX.
- 如果TX不是T,则执行从TX到T的标准显式转换.
在这里,S并且SX都是Program,所以第一部分什么都不做.TX被选择为long与T为目标类型,decimal,所以最后部分执行从标准转换long到decimal.
| 归档时间: |
|
| 查看次数: |
563 次 |
| 最近记录: |