C# 强制转换和强制转换有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8857763/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the difference between casting and coercing?
提问by Alexandr Kurilin
I've seen both terms be used almost interchangeably in various online explanations, and most text books I've consulted are also not entirely clear about the distinction.
我已经看到这两个术语在各种在线解释中几乎可以互换使用,而且我查阅过的大多数教科书也没有完全清楚区别。
Is there perhaps a clear and simple way of explaining the difference that you guys know of?
是否有一种清晰而简单的方法来解释你们所知道的差异?
Type conversion(also sometimes known as type cast)
To use a value of one type in a context that expects another.
Nonconverting type cast(sometimes known as type pun)
A change that does not alter the underlying bits.
Coercion
Process by which a compiler automatically converts a value of one type into a value of another type when that second type is required by the surrounding context.
类型转换(有时也被称为类型转换)
在需要另一种类型的上下文中使用一种类型的值。
非转换类型转换(有时称为类型双关语)
不会改变底层位的更改。
强迫
当周围上下文需要第二种类型时,编译器自动将一种类型的值转换为另一种类型的值的过程。
采纳答案by Igor Oks
类型转换:
The word conversionrefers to either implicitly or explicitly changing a value from one data type to another, e.g. a 16-bit integer to a 32-bit integer.
The word coercionis used to denote an implicit conversion.
The word casttypically refers to an explicit type conversion (as opposed to an implicit conversion), regardless of whether this is a re-interpretation of a bit-pattern or a real conversion.
字转换是指隐式或显式地将值从一种数据类型更改为另一种数据类型,例如将 16 位整数更改为 32 位整数。
字胁迫用于表示的隐式转换。
cast这个词通常指的是显式类型转换(与隐式转换相反),无论这是对位模式的重新解释还是真正的转换。
So, coercion is implicit, cast is explicit, and conversion is any of them.
因此,强制是隐式的,强制转换是显式的,转换是其中任何一种。
Few examples (from the same source) :
几个例子(来自同一来源):
Coercion (implicit):
强制(隐式):
double d;
int i;
if (d > i) d = i;
Cast (explicit):
演员表(显式):
double da = 3.3;
double db = 3.3;
double dc = 3.4;
int result = (int)da + (int)db + (int)dc; //result == 9
回答by PedroC88
Casting is the process by which you treat an object type as another type, Coercing is converting one object to another.
强制转换是将对象类型视为另一种类型的过程,强制转换是将一个对象转换为另一个对象。
Note that in the former process there is no conversion involved, you have a type that you would like to treat as another, say for example, you have 3 different objects that inherit from a base type, and you have a method that will take that base type, at any point, if you now the specific child type, you can CAST it to what it is and use all the specific methods and properties of that object and that will not create a new instance of the object.
请注意,在前一个过程中不涉及转换,您有一个类型,您希望将其视为另一种类型,例如,您有 3 个从基类型继承的不同对象,并且您有一个方法可以接受该类型基类型,在任何时候,如果您现在是特定的子类型,您可以将它转换为它的样子并使用该对象的所有特定方法和属性,并且不会创建该对象的新实例。
On the other hand, coercing implies the creation of a new object in memory of the new type and then the original type would be copied over to the new one, leaving both objects in memory (until the Garbage Collectors takes either away, or both).
另一方面,强制意味着在新类型的内存中创建一个新对象,然后将原始类型复制到新类型,将两个对象都留在内存中(直到垃圾收集器带走其中一个或两者) .
回答by Prisoner ZERO
Below is a posting from the following article:
以下是以下文章的帖子:
The difference between coercion and casting is often neglected. I can see why; many languages have the same (or similar) syntax and terminology for both operations. Some languages may even refer to any conversion as “casting,” but the following explanation refers to concepts in the CTS.
强制转换和强制转换之间的区别经常被忽视。我明白为什么;许多语言对这两种操作具有相同(或相似)的语法和术语。某些语言甚至可能将任何转换称为“转换”,但以下解释指的是 CTS 中的概念。
If you are trying to assign a value of some type to a location of a different type, you can generate a value of the new type that has a similar meaning to the original. This is coercion. Coercion lets you use the new type by creating a new value that in some way resembles the original. Some coercions may discard data (e.g. converting the int 0x12345678 to the short 0x5678), while others may not (e.g. converting the int 0x00000008 to the short 0x0008, or the long 0x0000000000000008).
如果您尝试将某种类型的值分配给不同类型的位置,则可以生成与原始类型具有相似含义的新类型值。这是胁迫。Coercion 允许您通过创建一个在某种程度上类似于原始值的新值来使用新类型。一些强制可能会丢弃数据(例如将 int 0x12345678 转换为 short 0x5678),而其他强制可能不会(例如将 int 0x00000008 转换为 short 0x0008 或 long 0x00000000000000008)。
Recall that values can have multiple types. If your situation is slightly different, and you only want to select a different one of the value's types, casting is the tool for the job. Casting simply indicates that you wish to operate on a particular type that a value includes.
回想一下,值可以有多种类型。如果您的情况略有不同,并且您只想选择一种不同的值类型,则强制转换是该工作的工具。强制转换只是表明您希望对值包含的特定类型进行操作。
The difference at the code level varies from C# to IL. In C#, both casting and coercion look fairly similar:
代码级别的差异从 C# 到 IL。在 C# 中,强制转换和强制转换看起来非常相似:
static void ChangeTypes(int number, System.IO.Stream stream)
{
long longNumber = number;
short shortNumber = (short)number;
IDisposable disposableStream = stream;
System.IO.FileStream fileStream = (System.IO.FileStream)stream;
}
At the IL level they are quite different:
在 IL 级别,它们完全不同:
ldarg.0
conv.i8
stloc.0
ldarg.0
conv.i2
stloc.1
ldarg.1
stloc.2
ldarg.1
castclass [mscorlib]System.IO.FileStream
stloc.3
As for the logical level, there are some important differences. What's most important to remember is that coercion creates a new value, while casting does not. The identity of the original value and the value after casting are the same, while the identity of a coerced value differs from the original value; coersion creates a new, distinct instance, while casting does not. A corollary is that the result of casting and the original will always be equivalent (both in identity and equality), but a coerced value may or may not be equal to the original, and never shares the original identity.
至于逻辑层面,有一些重要的区别。要记住的最重要的一点是强制转换会创造一个新值,而强制转换则不会。原始值的标识和转换后的值相同,而强制值的标识与原始值不同;强制创建一个新的、独特的实例,而强制转换则不会。一个推论是,强制转换的结果和原始值总是等价的(在同一性和相等性上),但强制值可能等于也可能不等于原始值,并且永远不会共享原始身份。
It's easy to see the implications of coercion in the examples above, as the numeric types are always copied by value. Things get a bit trickier when you're working with reference types.
在上面的例子中很容易看出强制转换的含义,因为数字类型总是按值复制。当您使用引用类型时,事情会变得有点棘手。
class Name : Tuple<string, string>
{
public Name(string first, string last)
: base(first, last)
{
}
public static implicit operator string[](Name name)
{
return new string[] { name.Item1, name.Item2 };
}
}
In the example below, one conversion is a cast, while the other is a coercion.
在下面的示例中,一种转换是强制转换,而另一种是强制转换。
Tuple<string, string> tuple = name;
string[] strings = name;
After these conversions, tuple and name are equal, but strings is not equal to either of them. You could make the situation slightly better (or slightly more confusing) by implementing Equals() and operator ==() on the Name class to compare a Name and a string[]. These operators would “fix” the comparison issue, but you would still have two separate instances; any modification to strings would not be reflected in name or tuple, while changes to either one of name or tuple would be reflected in name and tuple, but not in strings.
经过这些转换,tuple 和 name 相等,但字符串不等于它们中的任何一个。您可以通过在 Name 类上实现 Equals() 和 operator ==() 来比较 Name 和 string[] 来使情况稍微好一点(或稍微更令人困惑)。这些运算符将“修复”比较问题,但您仍然会有两个单独的实例;对字符串的任何修改都不会反映在名称或元组中,而对名称或元组之一的更改将反映在名称和元组中,但不会反映在字符串中。
Although the example above was meant to illustrate some differences between casting and coercion, it also serves as a great example of why you should be extremely cautious about using conversion operators with reference types in C#.
尽管上面的示例旨在说明强制转换和强制转换之间的一些差异,但它也很好地说明了为什么在 C# 中使用具有引用类型的转换运算符时应极为谨慎。
回答by Eric Lippert
Usages vary, as you note.
正如您所注意到的,用法各不相同。
My personal usages are:
我个人的用法是:
A "cast" is the usage of a cast operator. A cast operator instructs the compiler that either (1) this expression is not known to be of the given type, but I promise you that the value will be of that type at runtime; the compiler is to treat the expression as being of the given type, and the runtime will produce an error if it is not, or (2) the expression is of a different type entirely, but there is a well-known way to associate instances of the expression's type with instances of the cast-to type. The compiler is instructed to generate code that performs the conversion. The attentive reader will note that these are opposites, which I think is a neat trick.
A "conversion" is an operation by which a value of one type is treated as a value of another type -- usually a different type, though an "identity conversion" is still a conversion, technically speaking. The conversion may be "representation changing", like int to double, or it might be "representation preserving" like string to object. Conversions may be "implicit", which do not require a cast, or "explicit", which do require a cast.
A "coercion" is a representation-changing implicit conversion.
“强制转换”是强制转换运算符的使用。强制转换运算符指示编译器 (1) 不知道此表达式属于给定类型,但我向您保证该值在运行时将属于该类型;编译器会将表达式视为给定类型,如果不是,则运行时将产生错误,或者 (2) 表达式完全属于不同类型,但有一种众所周知的关联实例的方法具有强制转换类型实例的表达式类型。指示编译器生成执行转换的代码。细心的读者会注意到这些是对立的,我认为这是一个巧妙的技巧。
“转换”是一种操作,通过这种操作,一种类型的值被视为另一种类型的值——通常是不同的类型,尽管从技术上讲,“身份转换”仍然是一种转换。转换可能是“表示改变”,比如 int 到 double,或者它可能是“表示保留”,比如字符串到对象。转换可以是不需要强制转换的“隐式”,也可以是需要强制转换的“显式”。
“强制”是一种改变表示的隐式转换。
回答by P.Brian.Mackey
Casting preserves the type of objects. Coercion does not.
强制转换保留了对象的类型。胁迫不行。
Coercionis taking the value of a type that is NOT assignment compatible and converting to a type that is assignment compatible. Here I perform a coercion because Int32does NOT inherit from Int64...so it's NOT assignment compatible. This is a widening coercion (no data lost). A widening coercion is a.k.a. an implicit conversion. A Coercion performs a conversion.
Coercion正在获取与赋值不兼容的类型的值并转换为与赋值兼容的类型。在这里我执行强制转换,因为Int32它不继承自Int64... 所以它不兼容赋值。这是一种不断扩大的强制(不丢失数据)。扩大强制也称为隐式转换。 强制执行转换。
void Main()
{
System.Int32 a = 100;
System.Int64 b = a;
b.GetType();//The type is System.Int64.
}
Castingallows you to treat a type as if it were of a different type while also preserving the type.
强制转换允许您将类型视为不同的类型,同时还保留该类型。
void Main()
{
Derived d = new Derived();
Base bb = d;
//b.N();//INVALID. Calls to the type Derived are not possible because bb is of type Base
bb.GetType();//The type is Derived. bb is still of type Derived despite not being able to call members of Test
}
class Base
{
public void M() {}
}
class Derived: Base
{
public void N() {}
}
Source: The Common Language Infrastructure Annotated Standard by James S. Miller
资料来源:James S. Miller 的公共语言基础设施注释标准
Now what's odd is that Microsoft's documentation on Castingdoes not align with the ecma-335 specification definition of Casting.
现在奇怪的是,微软关于Casting的文档与Casting的 ecma-335 规范定义不一致。
Explicit conversions (casts): Explicit conversions require a cast operator. Casting is required when information might be lost in the conversion, or when the conversion might not succeed for other reasons. Typical examples include numeric conversion to a type that has less precision or a smaller range, and conversion of a base-class instance to a derived class.
显式转换(强制转换):显式转换需要强制转换运算符。当信息可能在转换中丢失,或者转换可能由于其他原因而无法成功时,需要进行转换。典型示例包括将数值转换为精度较低或范围较小的类型,以及将基类实例转换为派生类。
...This sounds like Coercionsnot Casting.
...这听起来像是强制而不是铸造。
For example,
例如,
object o = 1;
int i = (int)o;//Explicit conversions require a cast operator
i.GetType();//The type has been explicitly converted to System.Int32. Object type is not preserved. This meets the definition of Coercion not casting.
Who knows? Maybe Microsoft is checking if anybody reads this stuff.
谁知道?也许微软正在检查是否有人阅读这些东西。
回答by naglas
From the CLI standard:
从CLI 标准:
I.8.3.2 Coercion
Sometimes it is desirable to take a value of a type that is not assignable-to a location, and convert the value to a type that is assignable-to the type of the location. This is accomplished through coercionof the value. Coercion takes a value of a particular type and a desired type and attempts to create a value of the desired type that has equivalent meaning to the original value. Coercion can result in representation change as well as type change; hence coercion does not necessarily preserve object identity.
There are two kinds of coercion: widening, which never loses information, and narrowing, in which information might be lost. An example of a widening coercion would be coercing a value that is a 32-bit signed integer to a value that is a 64-bit signed integer. An example of a narrowing coercion is the reverse: coercing a 64-bit signed integer to a 32-bit signed integer. Programming languages often implement widening coercions as implicit conversions, whereas narrowing coercions usually require an explicit conversion.
Some coercion is built directly into the VES operations on the built-in types (see §I.12.1). All other coercion shall be explicitly requested. For the built-in types, the CTS provides operations to perform widening coercions with no runtime checks and narrowing coercions with runtime checks or truncation, according to the operation semantics.
I.8.3.3 Casting
Since a value can be of more than one type, a use of the value needs to clearly identify which of its types is being used. Since values are read from locations that are typed, the type of the value which is used is the type of the location from which the value was read. If a different type is to be used, the value is castto one of its other types. Casting is usually a compile time operation, but if the compiler cannot statically know that the value is of the target type, a runtime cast check is done. Unlike coercion, a cast never changes the actual type of an object nor does it change the representation. Casting preserves the identity of objects.
For example, a runtime check might be needed when casting a value read from a location that is typed as holding a value of a particular interface. Since an interface is an incomplete description of the value, casting that value to be of a different interface type will usually result in a runtime cast check.
I.8.3.2 强制
有时需要取不可分配给位置的类型的值,并将该值转换为可分配给位置的类型的类型。这是通过强制值来实现 的。强制采用特定类型和所需类型的值,并尝试创建与原始值具有等效含义的所需类型的值。强制可以导致表示形式的变化以及类型的变化;因此强制并不一定保留对象身份。
强制有两种类型:加宽,它永远不会丢失信息,和缩小,其中信息可能会丢失。扩展强制的一个例子是将一个 32 位有符号整数的值强制转换为一个 64 位有符号整数的值。收缩强制的一个例子是相反的:将 64 位有符号整数强制为 32 位有符号整数。编程语言通常将扩大强制转换为隐式转换,而缩小强制转换通常需要显式转换。
某些强制直接内置于内置类型的 VES 操作中(参见 §I.12.1)。所有其他强制都应明确要求。对于内置类型,根据操作语义,CTS 提供操作以执行没有运行时检查的加宽强制和使用运行时检查或截断的缩小强制。
I.8.3.3 铸造
由于一个值可以是多个类型,因此使用该值时需要清楚地确定正在使用的是哪种类型。由于值是从键入的位置读取的,因此所使用的值的类型是读取值的位置的类型。如果要使用不同的类型,则将该值强制转换为其其他类型之一。转换通常是一个编译时操作,但如果编译器不能静态地知道该值是目标类型,则执行运行时转换检查。与强制不同,强制转换不会改变对象的实际类型,也不会改变表示。强制转换保留了对象的身份。
例如,当转换从类型为保存特定接口值的位置读取的值时,可能需要运行时检查。由于接口是对值的不完整描述,因此将该值转换为不同的接口类型通常会导致运行时转换检查。
回答by Palak Jain
According to Wikipedia,
根据维基百科,
In computer science, type conversion, type casting, type coercion, and type juggling are different ways of changing an expression from one data type to another.
在计算机科学中,类型转换、类型转换、类型强制和类型杂耍是将表达式从一种数据类型更改为另一种数据类型的不同方式。
The difference between type casting and type coercion is as follows:
类型转换和类型强制的区别如下:
TYPE CASTING | TYPE COERCION
|
1. Explicit i.e., done by user | 1. Implicit i.e., done by the compiler
|
2. Types: | 2. Type:
Static (done at compile time) | Widening (conversion to higher data
| type)
Dynamic (done at run time) | Narrowing (conversion to lower data
| type)
|
3. Casting never changes the | 3. Coercion can result in representation
the actual type of object | as well as type change.
nor representation. |
Note: Casting is not conversion. It is just the process by which we treat an object type as another type. Therefore, the actual type of object, as well as the representation, is not changed during casting.
注意:铸造不是转换。这只是我们将对象类型视为另一种类型的过程。因此,对象的实际类型以及表示形式在转换期间不会改变。
I agree with @PedroC88's words:
我同意@PedroC88 的话:
On the other hand, coercing implies the creation of a new object in memory of the new type and then the original type would be copied over to the new one, leaving both objects in memory (until the Garbage Collectors takes either away, or both).
另一方面,强制意味着在新类型的内存中创建一个新对象,然后将原始类型复制到新类型,将两个对象都保留在内存中(直到垃圾收集器带走其中一个或两者) .

