Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “为什么可以转换?”;(详)(反对)";要从类型参数编译吗?_C# - Fatal编程技术网

C# “为什么可以转换?”;(详)(反对)";要从类型参数编译吗?

C# “为什么可以转换?”;(详)(反对)";要从类型参数编译吗?,c#,C#,来自C#5.0语言规范: 上述规则不允许从 非接口类型的无约束类型参数,可能是 令人惊讶的制定这条规则的原因是为了防止混淆和使 这种转换的语义很清楚。例如,考虑 以下声明: class X<T> { public static long F(T t) { return (long)t; // Error } } 此代码现在将编译,但执行X.F(7)将 在运行时引发异常,因为装箱的int无法转换 直接到一个长的 为什么添加(对象)会使编译工

来自C#5.0语言规范:

上述规则不允许从 非接口类型的无约束类型参数,可能是 令人惊讶的制定这条规则的原因是为了防止混淆和使 这种转换的语义很清楚。例如,考虑 以下声明:

class X<T> 
{ 
  public static long F(T t) { 
    return (long)t;        // Error  
  } 
} 
此代码现在将编译,但执行
X.F(7)
将 在运行时引发异常,因为装箱的int无法转换 直接到一个长的

为什么添加
(对象)
会使编译工作正常

在第一个示例中,如果我是正确的,
(long)t
中的
(long)
表示没有歧义的标准数字转换,这要求
t
的实际类型是一种可以通过
(long)
转换为long的数字类型。由于无法保证
t
的实际类型,因此编译失败

在第二个例子中

  • (long)(object)t
    中的
    (long)
    是否意味着取消装箱转换,而不会与其他类型的转换产生歧义

  • (long)(object)t
    中的
    (long)
    是否要求
    (object)t
    为盒装长字符?但是不能保证
    (object)t
    必须是一个装箱的长文本,那么为什么编译没有失败呢


谢谢。

第二个问题:编译成功是因为编译器允许这种“是的,我真的,真的是认真的”特殊情况,允许您处理逻辑上知道
t
将很长的情况,但编译器无法通过编译时的静态分析以某种方式证明这一点。如果你错了,它会抛出一个异常,这是你的问题。这并不是说你永远不能把一根绳子拉得太长,太长,太长,太长;这只是个例外。编译器只是帮了你一把,所以你不会完全出于偶然。谢谢。(1) 在第一个例子中,编译器是否认为
(long)t
只是标准的数字转换,或者可能是其他类型的转换,例如取消装箱?(2) 在第二个示例中,编译器是否只将
(long)(object)t
中的
(long)
看作是拆箱转换?编译器是否只将
(long)(object)t
中的
(object)
看作是装箱转换,或者可能是其他类型的转换,例如引用转换?我认为将object强制转换为long显然是拆箱;其余的,我不会冒险去猜。编译一些测试用例并转储MSIL可能是有益的;这将非常明确地告诉您编译器对转换的看法。还有一位前C#编译器团队成员,他经常光顾这里的C#标签,他对解释非常慷慨;您可能会收到他的来信。在示例1中,
(long)t
表示对
long
的任何有效转换,这可能包括数字转换,但也包括取消装箱转换。
T
不合法,因为如果源类型未知,编译器无法验证是否存在合法转换。示例2是合法的,因为与
对象
之间的转换对于
T
可以想象的任何类型都是合法的。我能想到的唯一不能与
object
转换的类型是指针,而
t
不能是指针类型。
(long)(object)
中的
(object)
可以是装箱转换或引用转换。应用的实际转换将取决于泛型实例化。当专门用于值类型时,它将是装箱转换。对于引用类型,请执行引用转换。它永远不会是用户定义的转换(自定义转换运算符)。第二个问题:编译成功是因为编译器允许这种“是的,我真的,真的是这么说的”特殊情况,允许您处理逻辑上知道
t
将很长的情况,但是编译器不能通过编译时的静态分析来证明这一点。如果你错了,它会抛出一个异常,这是你的问题。这并不是说你永远不能把一根绳子拉得太长,太长,太长,太长;这只是个例外。编译器只是帮了你一把,所以你不会完全出于偶然。谢谢。(1) 在第一个例子中,编译器是否认为
(long)t
只是标准的数字转换,或者可能是其他类型的转换,例如取消装箱?(2) 在第二个示例中,编译器是否只将
(long)(object)t
中的
(long)
看作是拆箱转换?编译器是否只将
(long)(object)t
中的
(object)
看作是装箱转换,或者可能是其他类型的转换,例如引用转换?我认为将object强制转换为long显然是拆箱;其余的,我不会冒险去猜。编译一些测试用例并转储MSIL可能是有益的;这将非常明确地告诉您编译器对转换的看法。还有一位前C#编译器团队成员,他经常光顾这里的C#标签,他对解释非常慷慨;您可能会收到他的来信。在示例1中,
(long)t
表示对
long
的任何有效转换,这可能包括数字转换,但也包括取消装箱转换。
T
不合法,因为如果源类型未知,编译器无法验证是否存在合法转换。示例2是合法的,因为与
对象
之间的转换对于
T
可以想象的任何类型都是合法的。我能想到的唯一不能与
object
转换的类型是指针,而
t
不能是指针类型。
(long)(object)
中的
(object)
可以是装箱转换或引用转换。实际情况
class X<T> 
{ 
  public static long F(T t) { 
    return (long)(object)t;   // Ok, but will only work when T is long 
  } 
}