# 转换Conversions

int a = 123;
long b = a;         // implicit conversion from int to long
int c = (int) b;    // explicit conversion from long to int


## 隐式转换Implicit conversions

• 标识转换Identity conversions
• 隐式数值转换Implicit numeric conversions
• 隐式枚举转换Implicit enumeration conversions
• 隐式内插字符串转换Implicit interpolated string conversions
• 隐式可为 null 转换Implicit nullable conversions
• Null 文本转换Null literal conversions
• 隐式引用转换Implicit reference conversions
• 装箱转换Boxing conversions
• 隐式动态转换Implicit dynamic conversions
• 隐式常量表达式转换Implicit constant expression conversions
• 用户定义的隐式转换User-defined implicit conversions
• 匿名函数转换Anonymous function conversions
• 方法组转换Method group conversions

### 标识转换Identity conversion

• 因为 objectdynamic 被视为等效的，所以在 objectdynamic之间存在标识转换，并且在用 dynamic 替换所有匹配项时，构造类型之间是相同的。Because object and dynamic are considered equivalent there is an identity conversion between object and dynamic, and between constructed types that are the same when replacing all occurrences of dynamic with object.

### 隐式数值转换Implicit numeric conversions

• sbyteshortintlongfloatdoubledecimalFrom sbyte to short, int, long, float, double, or decimal.
• byteshortushortintuintlongulongfloatdoubledecimalFrom byte to short, ushort, int, uint, long, ulong, float, double, or decimal.
• shortintlongfloatdoubledecimalFrom short to int, long, float, double, or decimal.
• ushortintuintlongulongfloatdoubledecimalFrom ushort to int, uint, long, ulong, float, double, or decimal.
• intlongfloatdoubledecimalFrom int to long, float, double, or decimal.
• uintlongulongfloatdoubledecimalFrom uint to long, ulong, float, double, or decimal.
• longfloatdoubledecimalFrom long to float, double, or decimal.
• ulongfloatdoubledecimalFrom ulong to float, double, or decimal.
• charushortintuintlongulongfloatdoubledecimalFrom char to ushort, int, uint, long, ulong, float, double, or decimal.
• floatdoubleFrom float to double.

intuintlongulongfloat 以及从 longulongdouble 的转换可能会导致精度损失，但永远不会导致数量级损失。Conversions from int, uint, long, or ulong to float and from long or ulong to double may cause a loss of precision, but will never cause a loss of magnitude. 其他隐式数值转换不会丢失任何信息。The other implicit numeric conversions never lose any information.

### 隐式可为 null 转换Implicit nullable conversions

• S?T?的隐式转换。An implicit conversion from S? to T?.
• ST?的隐式转换。An implicit conversion from S to T?.

• 如果可为 null 的转换来自 S?T?If the nullable conversion is from S? to T?:

• 如果源值为 null （HasValue 属性为 false），则结果为类型 T?的 null 值。If the source value is null (HasValue property is false), the result is the null value of type T?.
• 否则，转换将作为从 S?S的解包进行计算，后跟从 ST的底层转换，后跟从 TT?的包装（可为 null 的类型）。Otherwise, the conversion is evaluated as an unwrapping from S? to S, followed by the underlying conversion from S to T, followed by a wrapping (Nullable types) from T to T?.
• 如果将可为 null 的转换来自 ST?，则会将转换计算为从 ST 后跟从 TT?的基础转换。If the nullable conversion is from S to T?, the conversion is evaluated as the underlying conversion from S to T followed by a wrapping from T to T?.

### 隐式引用转换Implicit reference conversions

• 从任何reference_typeobjectdynamicFrom any reference_type to object and dynamic.
• 从任何class_type S 到任何class_type T，提供的 S 派生自 TFrom any class_type S to any class_type T, provided S is derived from T.
• 从任何class_type S 到任何interface_type T，提供 S 实现 TFrom any class_type S to any interface_type T, provided S implements T.
• 从任何interface_type S 到任何interface_type T，提供的 S 派生自 TFrom any interface_type S to any interface_type T, provided S is derived from T.
• 在元素类型为的array_type SSE 到元素类型 Tarray_type TE，前提是满足以下所有条件：From an array_type S with an element type SE to an array_type T with an element type TE, provided all of the following are true:
• ST 仅在元素类型上存在差异。S and T differ only in element type. 换句话说，ST 具有相同的维数。In other words, S and T have the same number of dimensions.
• SETE reference_typeBoth SE and TE are reference_types.
• 存在从 SETE的隐式引用转换。An implicit reference conversion exists from SE to TE.
• 从任何array_typeSystem.Array 及其实现的接口。From any array_type to System.Array and the interfaces it implements.
• 从一维数组类型 S[]System.Collections.Generic.IList<T> 及其基接口，前提是存在从 ST的隐式标识或引用转换。From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces, provided that there is an implicit identity or reference conversion from S to T.
• 从任何delegate_typeSystem.Delegate 及其实现的接口。From any delegate_type to System.Delegate and the interfaces it implements.
• 从 null 文本到任何reference_typeFrom the null literal to any reference_type.
• 从任何reference_typereference_type T 如果它具有隐式标识或到reference_type T0 的引用转换，并且 T0 的标识转换为 TFrom any reference_type to a reference_type T if it has an implicit identity or reference conversion to a reference_type T0 and T0 has an identity conversion to T.
• 从任何reference_type到接口或委托类型 T 如果它具有隐式标识或到接口或委托类型的引用转换 T0 并且 T0 可转换为 T的变体（差异转换）。From any reference_type to an interface or delegate type T if it has an implicit identity or reference conversion to an interface or delegate type T0 and T0 is variance-convertible (Variance conversion) to T.
• 涉及称为引用类型的类型参数的隐式转换。Implicit conversions involving type parameters that are known to be reference types. 有关涉及类型参数的隐式转换的更多详细信息，请参阅涉及类型参数的隐式转换See Implicit conversions involving type parameters for more details on implicit conversions involving type parameters.

### 装箱转换Boxing conversions

non_nullable_value_type的值装箱包括分配对象实例并将value_type值复制到该实例中。Boxing a value of a non_nullable_value_type consists of allocating an object instance and copying the value_type value into that instance. 结构可以装箱到类型 System.ValueType，因为这是所有结构（继承）的基类。A struct can be boxed to the type System.ValueType, since that is a base class for all structs (Inheritance).

nullable_type的值装箱将继续执行以下操作：Boxing a value of a nullable_type proceeds as follows:

• 如果源值为 null （HasValue 属性为 false），则结果为目标类型的空引用。If the source value is null (HasValue property is false), the result is a null reference of the target type.
• 否则，结果是对通过解包和装箱源值生成的装箱 T 的引用。Otherwise, the result is a reference to a boxed T produced by unwrapping and boxing the source value.

### 隐式动态转换Implicit dynamic conversions

object o  = "object"
dynamic d = "dynamic";

string s1 = o; // Fails at compile-time -- no conversion exists
string s2 = d; // Compiles and succeeds at run-time
int i     = d; // Compiles but fails at run-time -- no conversion exists


s2i 的分配都采用隐式动态转换，在这种情况下，将在运行时暂停操作的绑定。The assignments to s2 and i both employ implicit dynamic conversions, where the binding of the operations is suspended until run-time. 在运行时，隐式转换是从 d -- string--到目标类型的运行时类型中查找的。At run-time, implicit conversions are sought from the run-time type of d -- string -- to the target type. 找到 string 但不能 int的转换。A conversion is found to string but not to int.

### 隐式常量表达式转换Implicit constant expression conversions

• 如果 short 的值在目标类型的范围内，则可以将 int 类型的constant_expression常数表达式）转换为类型 sbytebyteushortuintulong或 constant_expression。A constant_expression (Constant expressions) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant_expression is within the range of the destination type.
• long 类型的constant_expression可转换为类型 ulong，前提是constant_expression的值不是负数。A constant_expression of type long can be converted to type ulong, provided the value of the constant_expression is not negative.

### 涉及类型参数的隐式转换Implicit conversions involving type parameters

T的给定类型参数存在以下隐式转换：The following implicit conversions exist for a given type parameter T:

• T 到其有效的基类 C，从 TC的任何基类，从 TC实现的任何接口。From T to its effective base class C, from T to any base class of C, and from T to any interface implemented by C. 在运行时，如果 T 是值类型，则转换将作为装箱转换执行。At run-time, if T is a value type, the conversion is executed as a boxing conversion. 否则，转换将作为隐式引用转换或标识转换执行。Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
• T 到接口类型 IT的有效接口集中，并从 TI的任何基接口。From T to an interface type I in T's effective interface set and from T to any base interface of I. 在运行时，如果 T 是值类型，则转换将作为装箱转换执行。At run-time, if T is a value type, the conversion is executed as a boxing conversion. 否则，转换将作为隐式引用转换或标识转换执行。Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
• T 到类型形参 U，提供 T 取决于 U类型形参约束）。From T to a type parameter U, provided T depends on U (Type parameter constraints). 在运行时，如果 U 是值类型，则 TU 都必须是相同的类型，并且不执行任何转换。At run-time, if U is a value type, then T and U are necessarily the same type and no conversion is performed. 否则，如果 T 是值类型，则转换将作为装箱转换执行。Otherwise, if T is a value type, the conversion is executed as a boxing conversion. 否则，转换将作为隐式引用转换或标识转换执行。Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
• 从 null 文本到 T，前提是已知 T 为引用类型。From the null literal to T, provided T is known to be a reference type.
• T 到引用类型 I 如果它具有到引用类型的隐式转换 S0 并且 S0 具有到 S的标识转换。From T to a reference type I if it has an implicit conversion to a reference type S0 and S0 has an identity conversion to S. 在运行时，转换的执行方式与转换到 S0的方式相同。At run-time the conversion is executed the same way as the conversion to S0.
• T 到接口类型 I 如果它具有到接口或委托类型的隐式转换 I0 并且 I0 可以转换为 I差异转换）。From T to an interface type I if it has an implicit conversion to an interface or delegate type I0 and I0 is variance-convertible to I (Variance conversion). 在运行时，如果 T 是值类型，则转换将作为装箱转换执行。At run-time, if T is a value type, the conversion is executed as a boxing conversion. 否则，转换将作为隐式引用转换或标识转换执行。Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.

## 显式转换Explicit conversions

• 所有隐式转换。All implicit conversions.
• 显式数值转换。Explicit numeric conversions.
• 显式枚举转换。Explicit enumeration conversions.
• 可以为 null 的显式转换。Explicit nullable conversions.
• 显式引用转换。Explicit reference conversions.
• 显式接口转换。Explicit interface conversions.
• 取消装箱转换。Unboxing conversions.
• 显式动态转换Explicit dynamic conversions
• 用户定义的显式转换。User-defined explicit conversions.

### 显式数值转换Explicit numeric conversions

• sbytebyteushortuintulongcharFrom sbyte to byte, ushort, uint, ulong, or char.
• bytesbytecharFrom byte to sbyte and char.
• shortsbytebyteushortuintulongcharFrom short to sbyte, byte, ushort, uint, ulong, or char.
• ushortsbytebyteshortcharFrom ushort to sbyte, byte, short, or char.
• intsbytebyteshortushortuintulongcharFrom int to sbyte, byte, short, ushort, uint, ulong, or char.
• uintsbytebyteshortushortintcharFrom uint to sbyte, byte, short, ushort, int, or char.
• longsbytebyteshortushortintuintulongcharFrom long to sbyte, byte, short, ushort, int, uint, ulong, or char.
• ulongsbytebyteshortushortintuintlongcharFrom ulong to sbyte, byte, short, ushort, int, uint, long, or char.
• charsbytebyteshortFrom char to sbyte, byte, or short.
• floatsbytebyteshortushortintuintlongulongchardecimalFrom float to sbyte, byte, short, ushort, int, uint, long, ulong, char, or decimal.
• doublesbytebyteshortushortintuintlongulongcharfloatdecimalFrom double to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or decimal.
• decimalsbytebyteshortushortintuintlongulongcharfloatdoubleFrom decimal to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or double.

• 对于从整型转换为另一整型类型的转换，处理过程取决于发生转换的溢出检查上下文（检查和未检查的运算符）：For a conversion from an integral type to another integral type, the processing depends on the overflow checking context (The checked and unchecked operators) in which the conversion takes place:
• checked 上下文中，如果源操作数的值在目标类型的范围内，则转换成功; 但如果源操作数的值超出了目标类型的范围，则会引发 System.OverflowExceptionIn a checked context, the conversion succeeds if the value of the source operand is within the range of the destination type, but throws a System.OverflowException if the value of the source operand is outside the range of the destination type.
• unchecked 上下文中，转换始终会成功，并按如下所示继续。In an unchecked context, the conversion always succeeds, and proceeds as follows.
• 如果源类型大于目标类型，则通过放弃其“额外”最高有效位来截断源值。If the source type is larger than the destination type, then the source value is truncated by discarding its "extra" most significant bits. 结果会被视为目标类型的值。The result is then treated as a value of the destination type.
• 如果源类型小于目标类型，则源值是符号扩展或零扩展，以使其与目标类型的大小相同。If the source type is smaller than the destination type, then the source value is either sign-extended or zero-extended so that it is the same size as the destination type. 如果源类型带符号，则是符号扩展；如果源类型是无符号的，则是零扩展。Sign-extension is used if the source type is signed; zero-extension is used if the source type is unsigned. 结果会被视为目标类型的值。The result is then treated as a value of the destination type.
• 如果源类型与目标类型的大小相同，则源值将被视为目标类型的值。If the source type is the same size as the destination type, then the source value is treated as a value of the destination type.
• 对于从 decimal 到整数类型的转换，将源值向零舍入到最接近的整数值，并且此整数值将成为转换的结果。For a conversion from decimal to an integral type, the source value is rounded towards zero to the nearest integral value, and this integral value becomes the result of the conversion. 如果生成的整数值超出了目标类型的范围，则会引发 System.OverflowExceptionIf the resulting integral value is outside the range of the destination type, a System.OverflowException is thrown.
• 对于从 floatdouble 到整数类型的转换，处理取决于发生转换的溢出检查上下文（检查和未检查的运算符）：For a conversion from float or double to an integral type, the processing depends on the overflow checking context (The checked and unchecked operators) in which the conversion takes place:
• checked 上下文中，转换过程如下所示：In a checked context, the conversion proceeds as follows:
• 如果操作数的值为 NaN 或无穷大，则会引发 System.OverflowExceptionIf the value of the operand is NaN or infinite, a System.OverflowException is thrown.
• 否则，源操作数向零舍入到最接近的整数值。Otherwise, the source operand is rounded towards zero to the nearest integral value. 如果此整数值在目标类型的范围内，则此值为转换的结果。If this integral value is within the range of the destination type then this value is the result of the conversion.
• 否则，将会引发 System.OverflowExceptionOtherwise, a System.OverflowException is thrown.
• unchecked 上下文中，转换始终会成功，并按如下所示继续。In an unchecked context, the conversion always succeeds, and proceeds as follows.
• 如果操作数的值为 NaN 或无穷大，则转换的结果是目标类型的未指定值。If the value of the operand is NaN or infinite, the result of the conversion is an unspecified value of the destination type.
• 否则，源操作数向零舍入到最接近的整数值。Otherwise, the source operand is rounded towards zero to the nearest integral value. 如果此整数值在目标类型的范围内，则此值为转换的结果。If this integral value is within the range of the destination type then this value is the result of the conversion.
• 否则，转换的结果是目标类型的未指定值。Otherwise, the result of the conversion is an unspecified value of the destination type.
• 对于从 doublefloat的转换，double 值舍入为最接近的 float 值。For a conversion from double to float, the double value is rounded to the nearest float value. 如果 double 值太小而无法表示为 float，则结果将变为零或负零。If the double value is too small to represent as a float, the result becomes positive zero or negative zero. 如果 double 值太大而无法表示为 float，则结果将变为正无穷或负无穷。If the double value is too large to represent as a float, the result becomes positive infinity or negative infinity. 如果 double 值为 NaN，则结果也为 NaN。If the double value is NaN, the result is also NaN.
• 对于从 floatdoubledecimal的转换，将源值转换为 decimal 表示形式，并在需要时舍入到第28位小数后最接近的数（decimal 类型）。For a conversion from float or double to decimal, the source value is converted to decimal representation and rounded to the nearest number after the 28th decimal place if required (The decimal type). 如果源值太小而无法表示为 decimal，则结果将变为零。If the source value is too small to represent as a decimal, the result becomes zero. 如果源值为 NaN、无限大或太大而无法表示为 decimal，则会引发 System.OverflowExceptionIf the source value is NaN, infinity, or too large to represent as a decimal, a System.OverflowException is thrown.
• 对于从 decimalfloatdouble的转换，decimal 值舍入为最接近的 doublefloat 值。For a conversion from decimal to float or double, the decimal value is rounded to the nearest double or float value. 虽然这种转换可能会丢失精度，但它永远不会引发异常。While this conversion may lose precision, it never causes an exception to be thrown.

### 显式枚举转换Explicit enumeration conversions

• sbytebyteshortushortintuintlongulongcharfloatdoubledecimal 到任何enum_typeFrom sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or decimal to any enum_type.
• 从任何enum_typesbytebyteshortushortintuintlongulongcharfloatdoubledecimalFrom any enum_type to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or decimal.
• 从任何enum_type到任何其他enum_typeFrom any enum_type to any other enum_type.

### 显式可为 null 的转换Explicit nullable conversions

• S?T?的显式转换。An explicit conversion from S? to T?.
• ST?的显式转换。An explicit conversion from S to T?.
• S?T的显式转换。An explicit conversion from S? to T.

• 如果可为 null 的转换来自 S?T?If the nullable conversion is from S? to T?:
• 如果源值为 null （HasValue 属性为 false），则结果为类型 T?的 null 值。If the source value is null (HasValue property is false), the result is the null value of type T?.
• 否则，转换将作为从 S?S的解包进行计算，后跟从 ST的底层转换，然后是从 TT?的包装。Otherwise, the conversion is evaluated as an unwrapping from S? to S, followed by the underlying conversion from S to T, followed by a wrapping from T to T?.
• 如果将可为 null 的转换来自 ST?，则会将转换计算为从 ST 后跟从 TT?的基础转换。If the nullable conversion is from S to T?, the conversion is evaluated as the underlying conversion from S to T followed by a wrapping from T to T?.
• 如果将可为 null 的转换来自 S?T，则会将转换计算为从 S?S 的解包，后跟从 ST的基础转换。If the nullable conversion is from S? to T, the conversion is evaluated as an unwrapping from S? to S followed by the underlying conversion from S to T.

### 显式引用转换Explicit reference conversions

• objectdynamic 到任何其他reference_typeFrom object and dynamic to any other reference_type.
• 从任何class_type S 到任何class_type T，提供的 ST的基类。From any class_type S to any class_type T, provided S is a base class of T.
• 从任何class_type S 到任何interface_type T，提供的 S 不是密封的，S 未实现 TFrom any class_type S to any interface_type T, provided S is not sealed and provided S does not implement T.
• 从任何interface_type S 到任何class_type T，提供的 T 未密封或未提供 T 实现 SFrom any interface_type S to any class_type T, provided T is not sealed or provided T implements S.
• 从任何interface_type S 到任何interface_type T，提供的 S 不是从 T派生的。From any interface_type S to any interface_type T, provided S is not derived from T.
• 在元素类型为的array_type SSE 到元素类型 Tarray_type TE，前提是满足以下所有条件：From an array_type S with an element type SE to an array_type T with an element type TE, provided all of the following are true:
• ST 仅在元素类型上存在差异。S and T differ only in element type. 换句话说，ST 具有相同的维数。In other words, S and T have the same number of dimensions.
• SETE reference_typeBoth SE and TE are reference_types.
• 存在从 SETE的显式引用转换。An explicit reference conversion exists from SE to TE.
• System.Array 及其实现的接口到任何array_typeFrom System.Array and the interfaces it implements to any array_type.
• 从一维数组类型 S[]System.Collections.Generic.IList<T> 及其基接口，前提是存在从 ST的显式引用转换。From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces, provided that there is an explicit reference conversion from S to T.
• System.Collections.Generic.IList<S> 及其基接口到一维数组类型 T[]，前提是有显式标识或从 ST的引用转换。From System.Collections.Generic.IList<S> and its base interfaces to a single-dimensional array type T[], provided that there is an explicit identity or reference conversion from S to T.
• System.Delegate 及其实现的接口到任何delegate_typeFrom System.Delegate and the interfaces it implements to any delegate_type.
• 从引用类型到引用类型 T 如果它具有到引用类型的显式引用转换 T0 并且 T0 具有 T的标识转换。From a reference type to a reference type T if it has an explicit reference conversion to a reference type T0 and T0 has an identity conversion T.
• 从引用类型到接口或委托类型 T 如果它具有到接口或委托类型的显式引用转换 T0 并且 T0 可以转换为 TT 变体转换为 T0变体转换）。From a reference type to an interface or delegate type T if it has an explicit reference conversion to an interface or delegate type T0 and either T0 is variance-convertible to T or T is variance-convertible to T0 (Variance conversion).
• D<S1...Sn>D<T1...Tn>，其中 D<X1...Xn> 是一个泛型委托类型，D<S1...Sn>D<T1...Tn>不兼容或等同于 Xi，而对于每个类型参数 D，则以下保留：From D<S1...Sn> to D<T1...Tn> where D<X1...Xn> is a generic delegate type, D<S1...Sn> is not compatible with or identical to D<T1...Tn>, and for each type parameter Xi of D the following holds:
• 如果 Xi 固定，则 SiTi相同。If Xi is invariant, then Si is identical to Ti.
• 如果 Xi 是协变的，则存在从 SiTi的隐式或显式标识或引用转换。If Xi is covariant, then there is an implicit or explicit identity or reference conversion from Si to Ti.
• 如果 Xi 为逆变，则 SiTi 均为相同或同时为这两个引用类型。If Xi is contravariant, then Si and Ti are either identical or both reference types.
• 涉及称为引用类型的类型参数的显式转换。Explicit conversions involving type parameters that are known to be reference types. 有关涉及类型参数的显式转换的详细信息，请参阅涉及类型参数的显式转换For more details on explicit conversions involving type parameters, see Explicit conversions involving type parameters.

### 显式动态转换Explicit dynamic conversions

class C
{
int i;

public C(int i) { this.i = i; }

public static explicit operator C(string s)
{
return new C(int.Parse(s));
}
}


object o  = "1";
dynamic d = "2";

var c1 = (C)o; // Compiles, but explicit reference conversion fails
var c2 = (C)d; // Compiles and user defined conversion succeeds


### 涉及类型参数的显式转换Explicit conversions involving type parameters

T的给定类型参数存在以下显式转换：The following explicit conversions exist for a given type parameter T:

• 从有效的基类 CTT 和从 C 的任何基类到 TFrom the effective base class C of T to T and from any base class of C to T. 在运行时，如果 T 是值类型，则转换将作为取消装箱转换执行。At run-time, if T is a value type, the conversion is executed as an unboxing conversion. 否则，转换将作为显式引用转换或标识转换执行。Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
• 从任何接口类型到 TFrom any interface type to T. 在运行时，如果 T 是值类型，则转换将作为取消装箱转换执行。At run-time, if T is a value type, the conversion is executed as an unboxing conversion. 否则，转换将作为显式引用转换或标识转换执行。Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
• T 到任何interface_type I 如果尚未从 TI的隐式转换。From T to any interface_type I provided there is not already an implicit conversion from T to I. 在运行时，如果 T 是值类型，则转换将作为装箱转换执行，后跟显式引用转换。At run-time, if T is a value type, the conversion is executed as a boxing conversion followed by an explicit reference conversion. 否则，转换将作为显式引用转换或标识转换执行。Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
• 从类型参数 UT，提供 T 依赖于 U类型参数约束）。From a type parameter U to T, provided T depends on U (Type parameter constraints). 在运行时，如果 U 是值类型，则 TU 都必须是相同的类型，并且不执行任何转换。At run-time, if U is a value type, then T and U are necessarily the same type and no conversion is performed. 否则，如果 T 是值类型，则转换将作为取消装箱转换执行。Otherwise, if T is a value type, the conversion is executed as an unboxing conversion. 否则，转换将作为显式引用转换或标识转换执行。Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.

class X<T>
{
public static long F(T t) {
return (long)t;                // Error
}
}


class X<T>
{
public static long F(T t) {
return (long)(object)t;        // Ok, but will only work when T is long
}
}


## 用户定义的转换User-defined conversions

C#允许使用用户定义的转换来扩充预定义的隐式和显式转换。C# allows the pre-defined implicit and explicit conversions to be augmented by user-defined conversions. 用户定义的转换通过在类和结构类型中声明转换运算符（转换运算符）引入。User-defined conversions are introduced by declaring conversion operators (Conversion operators) in class and struct types.

### 允许的用户定义的转换Permitted user-defined conversions

C#仅允许声明某些用户定义的转换。C# permits only certain user-defined conversions to be declared. 特别是，不能重新定义已存在的隐式或显式转换。In particular, it is not possible to redefine an already existing implicit or explicit conversion.

• S0T0 属于不同类型。S0 and T0 are different types.
• S0T0 是发生运算符声明的类或结构类型。Either S0 or T0 is the class or struct type in which the operator declaration takes place.
• S0T0 都不是interface_type的。Neither S0 nor T0 is an interface_type.
• 如果不包括用户定义的转换，则从 ST 或从 TS的转换不存在。Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.

### 计算用户定义的转换Evaluation of user-defined conversions

• 查找要将用户定义的转换运算符视为其中的一组类和结构。Finding the set of classes and structs from which user-defined conversion operators will be considered. 此集由源类型及其基类和目标类型及其基类组成（隐式假设只有类和结构可以声明用户定义的运算符，而非类类型没有基类）。This set consists of the source type and its base classes and the target type and its base classes (with the implicit assumptions that only classes and structs can declare user-defined operators, and that non-class types have no base classes). 对于此步骤，如果源类型或目标类型为nullable_type，则改为使用它们的基础类型。For the purposes of this step, if either the source or target type is a nullable_type, their underlying type is used instead.
• 从该类型集中确定哪些用户定义的转换运算符适用。From that set of types, determining which user-defined and lifted conversion operators are applicable. 要使转换运算符适用，必须可以执行标准转换（标准转换），使其从源类型转换为运算符的操作数类型，并且必须能够执行从运算符的结果类型到目标类型的标准转换。For a conversion operator to be applicable, it must be possible to perform a standard conversion (Standard conversions) from the source type to the operand type of the operator, and it must be possible to perform a standard conversion from the result type of the operator to the target type.
• 从一组适用的用户定义的运算符，确定哪个运算符明确是最具体的。From the set of applicable user-defined operators, determining which operator is unambiguously the most specific. 一般来说，最特定的运算符是操作数类型与源类型 "最接近" 的运算符，其结果类型与目标类型 "最近"。In general terms, the most specific operator is the operator whose operand type is "closest" to the source type and whose result type is "closest" to the target type. 用户定义的转换运算符优先于提升转换运算符。User-defined conversion operators are preferred over lifted conversion operators. 以下部分定义了用于建立最具体的用户定义转换运算符的确切规则。The exact rules for establishing the most specific user-defined conversion operator are defined in the following sections.

• 首先，如果需要，执行从源类型到用户定义或提升的转换运算符的操作数类型的标准转换。First, if required, performing a standard conversion from the source type to the operand type of the user-defined or lifted conversion operator.
• 接下来，调用用户定义或提升的转换运算符来执行转换。Next, invoking the user-defined or lifted conversion operator to perform the conversion.
• 最后，如果需要，执行从用户定义转换运算符的结果类型到目标类型的标准转换。Finally, if required, performing a standard conversion from the result type of the user-defined or lifted conversion operator to the target type.

• 如果从类型 A 到类型 B存在标准隐式转换（标准隐式转换），并且 AB 都不interface_type，则 A 被视为包含BB 称为包含AIf a standard implicit conversion (Standard implicit conversions) exists from a type A to a type B, and if neither A nor B are interface_types, then A is said to be encompassed by B, and B is said to encompass A.
• 一组类型中包含的最大的类型是一种包含集内所有其他类型的类型。The most encompassing type in a set of types is the one type that encompasses all other types in the set. 如果没有一种类型包含所有其他类型，则该集没有最大的包含类型。If no single type encompasses all other types, then the set has no most encompassing type. 更直观地说，最包含的类型是集中的 "最大" 类型，每个其他类型都可以隐式转换为一种类型。In more intuitive terms, the most encompassing type is the "largest" type in the set—the one type to which each of the other types can be implicitly converted.
• 类型集中最常被包含的类型是一种类型，它由集中的所有其他类型所包含。The most encompassed type in a set of types is the one type that is encompassed by all other types in the set. 如果所有其他类型都不包含任何一种类型，则该集不包含大多数被包含的类型。If no single type is encompassed by all other types, then the set has no most encompassed type. 更直观地说，最包含的类型是集中的 "最小" 类型，这种类型可以隐式转换为其他类型。In more intuitive terms, the most encompassed type is the "smallest" type in the set—the one type that can be implicitly converted to each of the other types.

### 处理用户定义的隐式转换Processing of user-defined implicit conversions

• 确定 S0T0的类型。Determine the types S0 and T0. 如果 ST 是可以为 null 的类型，S0T0 是其基础类型，则 S0T0 分别等于 STIf S or T are nullable types, S0 and T0 are their underlying types, otherwise S0 and T0 are equal to S and T respectively.
• 查找要将用户定义的转换运算符视为 D类型集。Find the set of types, D, from which user-defined conversion operators will be considered. 此集由 S0 （如果 S0 为类或结构）、S0 的基本类（如果 S0 是类）和 T0 （如果 T0 是类或结构）。This set consists of S0 (if S0 is a class or struct), the base classes of S0 (if S0 is a class), and T0 (if T0 is a class or struct).
• 查找一组适用的用户定义的转换运算符，UFind the set of applicable user-defined and lifted conversion operators, U. 此集由由 D 中的类或结构声明的用户定义的和提升的隐式转换运算符组成，它们从包含 S 的类型转换为 T包含的类型。This set consists of the user-defined and lifted implicit conversion operators declared by the classes or structs in D that convert from a type encompassing S to a type encompassed by T. 如果 U 为空，则转换未定义，并发生编译时错误。If U is empty, the conversion is undefined and a compile-time error occurs.
• 查找 U中运算符的最特定的源类型 SXFind the most specific source type, SX, of the operators in U:
• 如果 U 中的任何运算符从 S转换，则 SXSIf any of the operators in U convert from S, then SX is S.
• 否则，SXU中运算符的组合源类型集中最常包含的类型。Otherwise, SX is the most encompassed type in the combined set of source types of the operators in U. 如果找不到完全包含的类型，则转换是不明确的，并发生编译时错误。If exactly one most encompassed type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
• 查找 U中运算符的最特定目标类型 TXFind the most specific target type, TX, of the operators in U:
• 如果 U 中的任何运算符转换为 T，则 TXTIf any of the operators in U convert to T, then TX is T.
• 否则，TXU中运算符的组合目标类型集中最包含的类型。Otherwise, TX is the most encompassing type in the combined set of target types of the operators in U. 如果找不到完全包含的类型，则转换是不明确的，并发生编译时错误。If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
• 查找最具体的转换运算符：Find the most specific conversion operator:
• 如果 U 只包含一个从 SX 转换为 TX的用户定义的转换运算符，则这是最具体的转换运算符。If U contains exactly one user-defined conversion operator that converts from SX to TX, then this is the most specific conversion operator.
• 否则，如果 U 只包含一个从 SX 转换为 TX的提升转换运算符，则这是最具体的转换运算符。Otherwise, if U contains exactly one lifted conversion operator that converts from SX to TX, then this is the most specific conversion operator.
• 否则，转换是不明确的，并发生编译时错误。Otherwise, the conversion is ambiguous and a compile-time error occurs.
• 最后，应用转换：Finally, apply the conversion:
• 如果未 SXS，则执行从 SSX 的标准隐式转换。If S is not SX, then a standard implicit conversion from S to SX is performed.
• 调用最特定的转换运算符，以将 SX 转换为 TXThe most specific conversion operator is invoked to convert from SX to TX.
• 如果未 TTX，则执行从 TXT 的标准隐式转换。If TX is not T, then a standard implicit conversion from TX to T is performed.

### 处理用户定义的显式转换Processing of user-defined explicit conversions

• 确定 S0T0的类型。Determine the types S0 and T0. 如果 ST 是可以为 null 的类型，S0T0 是其基础类型，则 S0T0 分别等于 STIf S or T are nullable types, S0 and T0 are their underlying types, otherwise S0 and T0 are equal to S and T respectively.
• 查找要将用户定义的转换运算符视为 D类型集。Find the set of types, D, from which user-defined conversion operators will be considered. 此集由 S0 （如果 S0 为类或结构）、S0 （如果 S0 是类）的基类、T0 （如果 T0 是类或结构）以及 T0 （如果 T0 是类）的基类。This set consists of S0 (if S0 is a class or struct), the base classes of S0 (if S0 is a class), T0 (if T0 is a class or struct), and the base classes of T0 (if T0 is a class).
• 查找一组适用的用户定义的转换运算符，UFind the set of applicable user-defined and lifted conversion operators, U. 此集由 D 中的类或结构声明的用户定义的隐式或显式转换运算符，由 S 转换为包含 T包含或包含的类型。This set consists of the user-defined and lifted implicit or explicit conversion operators declared by the classes or structs in D that convert from a type encompassing or encompassed by S to a type encompassing or encompassed by T. 如果 U 为空，则转换未定义，并发生编译时错误。If U is empty, the conversion is undefined and a compile-time error occurs.
• 查找 U中运算符的最特定的源类型 SXFind the most specific source type, SX, of the operators in U:
• 如果 U 中的任何运算符从 S转换，则 SXSIf any of the operators in U convert from S, then SX is S.
• 否则，如果 U 中的任何运算符从包含 S的类型进行转换，则 SX 是这些运算符的一组源类型中包含程度最高的类型。Otherwise, if any of the operators in U convert from types that encompass S, then SX is the most encompassed type in the combined set of source types of those operators. 如果找不到最能包含的类型，则转换是不明确的，并发生编译时错误。If no most encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
• 否则，SXU中运算符的组合源类型集中的最包含的类型。Otherwise, SX is the most encompassing type in the combined set of source types of the operators in U. 如果找不到完全包含的类型，则转换是不明确的，并发生编译时错误。If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
• 查找 U中运算符的最特定目标类型 TXFind the most specific target type, TX, of the operators in U:
• 如果 U 中的任何运算符转换为 T，则 TXTIf any of the operators in U convert to T, then TX is T.
• 否则，如果 U 中的任何运算符转换为 T包含的类型，则在这些运算符的组合目标类型集中，TX 是最包含的类型。Otherwise, if any of the operators in U convert to types that are encompassed by T, then TX is the most encompassing type in the combined set of target types of those operators. 如果找不到完全包含的类型，则转换是不明确的，并发生编译时错误。If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
• 否则，TXU中运算符的组合目标类型集中最常被包含的类型。Otherwise, TX is the most encompassed type in the combined set of target types of the operators in U. 如果找不到最能包含的类型，则转换是不明确的，并发生编译时错误。If no most encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
• 查找最具体的转换运算符：Find the most specific conversion operator:
• 如果 U 只包含一个从 SX 转换为 TX的用户定义的转换运算符，则这是最具体的转换运算符。If U contains exactly one user-defined conversion operator that converts from SX to TX, then this is the most specific conversion operator.
• 否则，如果 U 只包含一个从 SX 转换为 TX的提升转换运算符，则这是最具体的转换运算符。Otherwise, if U contains exactly one lifted conversion operator that converts from SX to TX, then this is the most specific conversion operator.
• 否则，转换是不明确的，并发生编译时错误。Otherwise, the conversion is ambiguous and a compile-time error occurs.
• 最后，应用转换：Finally, apply the conversion:
• 如果未 SXS，则执行从 SSX 的标准显式转换。If S is not SX, then a standard explicit conversion from S to SX is performed.
• 调用最特定的用户定义转换运算符，以将 SX 转换为 TXThe most specific user-defined conversion operator is invoked to convert from SX to TX.
• 如果未 TTX，则执行从 TXT 的标准显式转换。If TX is not T, then a standard explicit conversion from TX to T is performed.

## 匿名函数转换Anonymous function conversions

Anonymous_method_expressionlambda_expression归类为匿名函数（匿名函数表达式）。An anonymous_method_expression or lambda_expression is classified as an anonymous function (Anonymous function expressions). 表达式没有类型，但可以隐式转换为兼容的委托类型或表达式树类型。The expression does not have a type but can be implicitly converted to a compatible delegate type or expression tree type. 具体而言，F 的匿名函数与 D 提供的委托类型兼容：Specifically, an anonymous function F is compatible with a delegate type D provided:

• 如果 F 包含anonymous_function_signature，则 DF 具有相同数量的参数。If F contains an anonymous_function_signature, then D and F have the same number of parameters.
• 如果 F 不包含anonymous_function_signature，则 D 可能具有零个或多个任意类型的参数，前提是没有 D 的参数具有 out 参数修饰符。If F does not contain an anonymous_function_signature, then D may have zero or more parameters of any type, as long as no parameter of D has the out parameter modifier.
• 如果 F 具有显式类型化参数列表，则 D 中的每个参数都具有与 F中的相应参数相同的类型和修饰符。If F has an explicitly typed parameter list, each parameter in D has the same type and modifiers as the corresponding parameter in F.
• 如果 F 具有隐式类型参数列表，则 D 没有 refout 参数。If F has an implicitly typed parameter list, D has no ref or out parameters.
• 如果 F 的主体是一个表达式，并且 D 具有 void 返回类型或 F 为 async 并且 D 具有返回类型 Task，则当 F 的每个参数都给定 D中的相应参数的类型时，F 的主体将被视为statement_expressionexpression 语句 ）。If the body of F is an expression, and either D has a void return type or F is async and D has the return type Task, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid expression (wrt Expressions) that would be permitted as a statement_expression (Expression statements).
• 如果 F 的主体是一个语句块，并且 D 具有 void 返回类型或 F 为 async 并且 D 具有返回类型 Task，则当 F 的每个参数都给定 D中对应参数的类型时，F 的主体为有效语句块（wrt），其中没有 return 语句指定表达式。If the body of F is a statement block, and either D has a void return type or F is async and D has the return type Task, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid statement block (wrt Blocks) in which no return statement specifies an expression.
• 如果 F 的主体是一个表达式，并且 F 为非 async 并且 D 具有非 void 返回类型 TF 为 async 并且 D 具有返回类型 Task<T>，则当 F 的每个参数都给定 D中对应参数的类型时，F 的主体是可隐式转换为 T的有效表达式（wrt表达式）。If the body of F is an expression, and either F is non-async and D has a non-void return type T, or F is async and D has a return type Task<T>, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid expression (wrt Expressions) that is implicitly convertible to T.
• 如果 F 的主体是一个语句块，并且 F 为非 async 并且 D 具有非 void 返回类型 TF 为 async 并且 D 具有返回类型 Task<T>，则当 F 的每个参数都给定 D中对应参数的类型时，F 的主体为有效语句块（wrt），其中每个 return 语句指定一个可隐式转换为 T的表达式。If the body of F is a statement block, and either F is non-async and D has a non-void return type T, or F is async and D has a return type Task<T>, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid statement block (wrt Blocks) with a non-reachable end point in which each return statement specifies an expression that is implicitly convertible to T.

• 具有Has a block body
• 包含简单赋值运算符或复合赋值运算符Contains simple or compound assignment operators
• 包含动态绑定的表达式Contains a dynamically bound expression
• 为异步Is async

delegate R Func<A,R>(A arg);


Func<int,int> f1 = x => x + 1;                 // Ok

Func<int,double> f2 = x => x + 1;              // Ok

Func<double,int> f3 = x => x + 1;              // Error

Func<int, Task<int>> f4 = async x => x + 1;    // Ok


### 匿名函数转换到委托类型的计算Evaluation of anonymous function conversions to delegate types

delegate double Function(double x);

class Test
{
static double[] Apply(double[] a, Function f) {
double[] result = new double[a.Length];
for (int i = 0; i < a.Length; i++) result[i] = f(a[i]);
return result;
}

static void F(double[] a, double[] b) {
a = Apply(a, (double x) => Math.Sin(x));
b = Apply(b, (double y) => Math.Sin(y));
...
}
}


### 实现示例Implementation example

public delegate void D();


class Test
{
static void F() {
D d = () => { Console.WriteLine("test"); };
}
}


class Test
{
static void F() {
D d = new D(__Method1);
}

static void __Method1() {
Console.WriteLine("test");
}
}


class Test
{
int x;

void F() {
D d = () => { Console.WriteLine(x); };
}
}


class Test
{
int x;

void F() {
D d = new D(__Method1);
}

void __Method1() {
Console.WriteLine(x);
}
}


class Test
{
void F() {
int y = 123;
D d = () => { Console.WriteLine(y); };
}
}


class Test
{
void F() {
__Locals1 __locals1 = new __Locals1();
__locals1.y = 123;
D d = new D(__locals1.__Method1);
}

class __Locals1
{
public int y;

public void __Method1() {
Console.WriteLine(y);
}
}
}


class Test
{
int x;

void F() {
int y = 123;
for (int i = 0; i < 10; i++) {
int z = i * 2;
D d = () => { Console.WriteLine(x + y + z); };
}
}
}


class Test
{
void F() {
__Locals1 __locals1 = new __Locals1();
__locals1.__this = this;
__locals1.y = 123;
for (int i = 0; i < 10; i++) {
__Locals2 __locals2 = new __Locals2();
__locals2.__locals1 = __locals1;
__locals2.z = i * 2;
D d = new D(__locals2.__Method1);
}
}

class __Locals1
{
public Test __this;
public int y;
}

class __Locals2
{
public __Locals1 __locals1;
public int z;

public void __Method1() {
Console.WriteLine(__locals1.__this.x + __locals1.y + z);
}
}
}


## 方法组转换Method group conversions

• 选择与窗体 E(A)的方法调用（方法调用）相对应 M 单个方法，并进行以下修改：A single method M is selected corresponding to a method invocation (Method invocations) of the form E(A), with the following modifications:
• 参数列表 A 是一个表达式列表，每个表达式都分类为一个变量，并且具有 Dformal_parameter_list中相应参数的类型和修饰符（refout）。The argument list A is a list of expressions, each classified as a variable and with the type and modifier (ref or out) of the corresponding parameter in the formal_parameter_list of D.
• 被视为的候选方法只是那些适用于其正常窗体（适用函数成员）的方法，而不是仅适用于其扩展窗体的方法。The candidate methods considered are only those methods that are applicable in their normal form (Applicable function member), not those applicable only in their expanded form.
• 如果方法调用的算法产生错误，则会发生编译时错误。If the algorithm of Method invocations produces an error, then a compile-time error occurs. 否则，算法将生成单个最佳方法，MD 具有相同数量的参数，并将转换视为存在。Otherwise the algorithm produces a single best method M having the same number of parameters as D and the conversion is considered to exist.
• 所选方法 M 必须兼容（委托兼容性D委托类型，否则将发生编译时错误。The selected method M must be compatible (Delegate compatibility) with the delegate type D, or otherwise, a compile-time error occurs.
• 如果所选方法 M 是实例方法，则与 E 关联的实例表达式确定委托的目标对象。If the selected method M is an instance method, the instance expression associated with E determines the target object of the delegate.
• 如果所选方法 M 是通过实例表达式上的成员访问方式表示的扩展方法，则该实例表达式将确定委托的目标对象。If the selected method M is an extension method which is denoted by means of a member access on an instance expression, that instance expression determines the target object of the delegate.
• 转换结果为类型 D的值，即引用所选方法和目标对象的新创建的委托。The result of the conversion is a value of type D, namely a newly created delegate that refers to the selected method and target object.
• 请注意，如果方法调用的算法未能找到实例方法，但在处理 E(A) 的调用作为扩展方法调用（扩展方法调用）时，此过程可能会导致创建扩展方法的委托。Note that this process can lead to the creation of a delegate to an extension method, if the algorithm of Method invocations fails to find an instance method but succeeds in processing the invocation of E(A) as an extension method invocation (Extension method invocations). 因此，创建的委托将捕获扩展方法以及其第一个参数。A delegate thus created captures the extension method as well as its first argument.

delegate string D1(object o);

delegate object D2(string s);

delegate object D3();

delegate string D4(object o, params object[] a);

delegate string D5(int i);

class Test
{
static string F(object o) {...}

static void G() {
D1 d1 = F;            // Ok
D2 d2 = F;            // Ok
D3 d3 = F;            // Error -- not applicable
D4 d4 = F;            // Error -- not applicable in normal form
D5 d5 = F;            // Error -- applicable but not compatible

}
}


d2 的赋值演示了如何创建一个委托，该委托指向的派生程度较低（逆变）的参数类型和派生程度更高（协变）返回类型的方法。The assignment to d2 shows how it is possible to create a delegate to a method that has less derived (contravariant) parameter types and a more derived (covariant) return type.

d4 的赋值显示了方法必须以其正常形式适用的方式。The assignment to d4 shows how the method must be applicable in its normal form.

d5 的赋值显示了如何允许委托和方法的参数和返回类型仅与引用类型不同。The assignment to d5 shows how parameter and return types of the delegate and method are allowed to differ only for reference types.

object obj = new EventHandler(myDialog.OkClick);


object obj = (EventHandler)myDialog.OkClick;


• 如果在编译时选择的方法是实例方法，或者它是作为实例方法访问的扩展方法，则将从与 E关联的实例表达式确定委托的目标对象：If the method selected at compile-time is an instance method, or it is an extension method which is accessed as an instance method, the target object of the delegate is determined from the instance expression associated with E:
• 计算实例表达式。The instance expression is evaluated. 如果此计算导致异常，则不执行其他步骤。If this evaluation causes an exception, no further steps are executed.
• 如果实例表达式为reference_type，则由实例表达式计算的值将成为目标对象。If the instance expression is of a reference_type, the value computed by the instance expression becomes the target object. 如果所选的方法是实例方法，并且目标对象是 null的，则会引发 System.NullReferenceException，而不执行进一步的步骤。If the selected method is an instance method and the target object is null, a System.NullReferenceException is thrown and no further steps are executed.
• 如果实例表达式为value_type，则将执行装箱操作（装箱转换）以将值转换为对象，此对象将成为目标对象。If the instance expression is of a value_type, a boxing operation (Boxing conversions) is performed to convert the value to an object, and this object becomes the target object.
• 否则，所选方法为静态方法调用的一部分，并且 null委托的目标对象。Otherwise the selected method is part of a static method call, and the target object of the delegate is null.
• 分配 D 委托类型的新实例。A new instance of the delegate type D is allocated. 如果内存不足，无法分配新的实例，则会引发 System.OutOfMemoryException，而不执行进一步的步骤。If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
• 使用对在编译时确定的方法以及对上面计算的目标对象的引用来初始化新的委托实例。The new delegate instance is initialized with a reference to the method that was determined at compile-time and a reference to the target object computed above.