在Jesse Liberty的Learning C#书中,他说"一种类型的物体可以转换成另一种类型的物体.这就是所谓的铸造."
如果您调查从下面的代码生成的IL,您可以清楚地看到转换的赋值与转换的赋值没有做同样的事情.在前者中,你可以看到拳击/拆箱发生; 在后者中,您可以看到对convert方法的调用.
我知道最终它可能只是一个愚蠢的语义差异 - 但是只是转换了另一个词.我并不是故意嗤之以鼻,但我对任何人的直觉都不感兴趣 - 意见不计算在这里!任何人都可以指出确认或否认铸造和转换是否相同的确定性参考?
object x; int y; x = 4; y = ( int )x; y = Convert.ToInt32( x );
谢谢
RP
注意在Matt关于显式/隐式的评论后添加:
我不认为隐含/显性是不同的.在我发布的代码中,两种情况下的更改都是明确的.隐式转换是指向int分配short时发生的情况.
Sklivvz注意事项:
我想要确认我对Jesse Liberty(通常是清晰和清晰)语言松散的怀疑是正确的.我以为Jesse Liberty的语言有点松散.我知道转换是在对象层次结构中路由的 - 也就是说,您不能从整数转换为字符串,但是您可以从从System.Exception派生的自定义异常转换为System.Exception.
但有趣的是,当您尝试从int转换为字符串时,编译器会告诉您它无法"转换"该值.也许杰西比我想象的更正确!
绝对不!
转换尝试通过"任何可能的方式"获取Int32.Cast没有做那种事.使用强制转换,您告诉编译器将对象视为Int,而不进行转换.
当您(通过设计)知道对象是Int32或其他具有Int32的转换运算符的类(例如float)时,应始终使用强制转换.
转换应与String一起使用,或与其他类一起使用.
试试这个
static void Main(string[] args) { long l = long.MaxValue; Console.WriteLine(l); byte b = (byte) l; Console.WriteLine(b); b = Convert.ToByte(l); Console.WriteLine(b); }
结果:
9223372036854775807
255
未处理的异常:
System.OverflowException:在/ home/marco中的Test.Main(System.String [] args)[0x00019]处的System.Convert.ToByte(Int64值)[0x00000]处的值大于Byte.MaxValue或小于Byte.MinValue /develop/test/Exceptions.cs:15
简单的答案是:它取决于.
对于值类型,转换将涉及将其真正转换为其他类型.例如:
float f = 1.5f; int i = (int) f; // Conversion
当转换表达式取消装箱时,结果(假设它有效)通常只是框中内容的副本,具有相同的类型.但是有一些例外 - 你可以从盒装的int到enum(底层类型为int)取消装箱,反之亦然; 同样,你可以从盒装int解包到Nullable
当转换表达式从一个引用类型到另一个引用类型并且不涉及用户定义的转换时,就对象本身而言,没有转换 - 只有引用的类型"改变" - 而这实际上只是值被视为,而不是引用本身(它将与以前相同).例如:
object o = "hello"; string x = (string) o; // No data is "converted"; x and o refer to the same object
当涉及用户定义的转换时,这通常需要返回不同的对象/值.例如,您可以为自己的类型定义转换为字符串 - 这肯定与您自己的对象不同.(当然,它可能是从您的对象引用的现有字符串.)根据我的经验,用户定义的转换通常存在于值类型而不是引用类型之间,因此这很少是一个问题.
所有这些都算作规范方面的转换 - 但它们并不都算作将对象转换为不同类型的对象.我怀疑这是一个Jesse Liberty的术语松散的例子 - 我注意到在C#3.0编程中,我刚读过这篇文章.
这涵盖了一切吗?
我见过的最好的解释可以在下面看到,然后链接到源:
"......真相比这更复杂..NET提供了三种从A点到B点的方法,就像它一样.
首先,有隐式演员.这是演员表,除了作业之外不需要你做任何事情:
int i = 5; double d = i;
这些也称为"扩展转换",.NET允许您在没有任何强制转换操作符的情况下执行它们,因为您永远不会丢失任何信息:double的有效值的可能范围包含int的有效值范围,然后一些,所以你永远不会做这个任务,然后发现你的恐惧,运行时从你的int值下降几位数.对于引用类型,隐式转换后面的规则是强制转换永远不会抛出InvalidCastException:编译器很清楚转换是否始终有效.
您可以为自己的类型创建新的隐式强制转换运算符(这意味着您可以进行隐式强制转换,如果您对此愚蠢,则会破坏所有规则).基本的经验法则是隐式演员阵容永远不会包含在过渡中丢失信息的可能性.
请注意,底层表示在此转换中确实发生了变化:double与int完全不同.
第二种转换是显式转换.只要有可能丢失信息,或者有可能转换可能无效并因此抛出InvalidCastException,则需要显式强制转换:
double d = 1.5; int i = (int)d;
在这里你显然会丢失信息:我会在演员阵容后成为1,所以0.5会丢失.这也称为"缩小"转换,编译器要求您包含一个显式的强制转换(int)来表示是,您知道信息可能会丢失,但您并不在意.
类似地,对于引用类型,编译器在运行时转换可能无效的情况下需要显式转换,作为信号,是的,您知道存在风险,但您知道自己在做什么.
第三种转换是涉及表示的一种根本改变,即设计师甚至不提供明确的演员:它们会让你调用方法来进行转换:
string s = "15"; int i = Convert.ToInt32(s);
请注意,这里绝对不需要方法调用.隐式和显式转换也是方法调用(这就是你自己制作的方法).设计人员可以很容易地创建一个将字符串转换为int的显式转换运算符.调用方法的要求是一种风格选择,而不是语言的基本要求.
风格推理是这样的:String-to-int是一个复杂的转换,有很多机会出现可怕的错误:
string s = "The quick brown fox"; int i = Convert.ToInt32(s);
因此,方法调用为您提供了阅读文档,并提供了一个广泛的暗示,即这不仅仅是一个快速演员.
在设计自己的类型(特别是您自己的值类型)时,您可能决定创建转换运算符和转换函数.划分"隐式演员","明确演员"和"转换函数"领域的界限有点模糊,因此不同的人可能会对应该是什么做出不同的决定.只是试着记住信息丢失,以及异常和无效数据的可能性,这应该有助于你做出决定."
布鲁斯伍德,2005年11月16日
http://bytes.com/forum/post1068532-4.html