Use IL to implement type conversion and il to implement type conversion

Source: Internet
Author: User

Use IL to implement type conversion and il to implement type conversion

In my previous articles, I have roughly introduced some implicit and explicit type conversion rules between types. However, CSharp Language Specification was not carefully studied at the time, so the implementation was incomplete. In addition, it only partially solves whether type conversion can be performed between types, but still does not solve how to perform type conversion, especially when defining generic types, we clearly know what type the parameter of the generic type is, but we cannot directly convert the type:

If (typeof (T) = typeof (int) {int intValue = (int) value; // error: the type "T" cannot be converted to "int "}

OnlyobjectType "transit:

if (typeof(T) == typeof(int)) {    int intValue = (int)(object)value;}

Here, the value-Type Packing/unpacking operations are used to avoid errors. But what if I want to be more general? For example, I knowcharType can be implicitly convertedintType, so can I write it like this:

if (typeof(T) == typeof(int) || typeof(T) == typeof(char)) {    int intValue = (int)(object)value;}

Unfortunately, ifvalueYescharType, the System. InvalidCastException: the specified conversion is invalid. Different types must be written separately. This is because most of the IL code for type conversion is completely determined during the compilation period. At runtime, only compatible reference type conversion (CastClass) and packing/unpacking (Box/Unbox) can be performed) conversion.

To enhance and simplify the type conversion during running, I carefully studied CSharp Language Specification and IL, and used System. reflection. emit implements a framework for dynamically generating IL for type conversion at runtime, which supports conversion of similar types as the compiler at runtime, and provides complete support for generic types. For example, the following section converts any numeric typeulong:

// Assume that the TValue must be of the numerical type. Public ulong ToUInt64 <TValue> (TValue value) {return Convert. ChangeType <TValue, ulong> (value );}

The main interface for type conversion is the Convert class, which can be fully compatibleVarious numeric type conversion, implicit/explicit reference type conversion, and user-defined type conversion, Including:

  • Get type converter:GetConverter<TInput, TOutput>()AndGetConverter(Type inputType, Type outputType)The resulting Converter <TInput, TOutput> delegate can be directly used for type conversion.
  • Directly convert the Data Type:ChangeType<TInput, TOutput>(TInput value),ChangeType<TOutput>(object value)AndChangeType(object value, Type outputType).
  • Determine whether type conversion can be performed:CanChangeType(Type inputType, Type outputType).
  • How to add a type conversion method during running:AddConverter<TInput, TOutput>(Converter<TInput, TOutput> converter)AndAddConverterProvider(IConverterProvider provider).

All type conversions are implemented by using System. Reflection. Emit to dynamically generate IL, ensuring the efficiency of type conversion. Therefore, the extension method EmitConversion of the ILGenerator class is also provided, and the type conversion can be performed when the IL code is generated.

All the above Code can be found in the Cyjb. Conversions and Cyjb. Reflection namespaces.

Next, I will briefly introduce how to use IL to implement type conversion.

I. predefined type conversion

According to CSharp Language Specification, pre-defined type conversion mainly includes: logo conversion, implicit numeric conversion, implicit enumeration conversion, and Nullable <T>) such as implicit conversion, implicit reference conversion, packing conversion, explicit numeric conversion, explicit enumeration conversion, Explicit conversions of the null type, explicit conversion of the explicit reference and box-breaking conversion. ByimplicitAndexplicitUser-Defined type conversion for keyword declaration will be introduced in the next section.

The process of these types of conversions is provided in the Specification, but the efficiency is very low if you simply judge these types of conversions in order. Therefore, I use the algorithm shown in the following code to make a judgment:

Figure 1 pre-defined type conversion judgment Algorithm

The IL commands used for pre-defined type conversion are generally relatively simple, basicallycastclass,boxAndunboxCommands, which are more complex than implicit/Explicit conversions and empty conversions.

I have summarized the following table for implicit/explicit numeric conversion, and its implementation is basically the process of Table query. At the top of the table is the IL command for no overflow check, and the IL command for overflow check. Spaces indicate that the type conversion can be performed without inserting the IL command. The green background indicates implicit value conversion, the yellow background indicates explicit Numerical Conversion:

Figure 2 implicit/explicit numeric Conversion

Note:There is a distinction between overflow checks (checked/unchecked) for Numeric conversions, and the Decimal type is not listed in the table, the conversion between the Decimal type and other numeric types relies on the type conversion method defined by implicit/explicit, which is not suitable for table search.

Can be empty type conversion, can be divided into three situations (SetS,TAll are non-empty value types ):

For information on possible empty conversions, see BetweenNullableConversion. cs, FromNullableConversion. cs, and ToNullableConversion. cs.

Ii. User-Defined type conversion

This refersimplicitAndexplicitCustom type conversion method for keyword declaration. The algorithm introduced below comes from CSharp Language Specification 6.4.5 User-defined explicit conversions. I will not distinguish between implicit type conversion and explicit type conversion, this distinction is not important at runtime.

First, we need to clarify some concepts.

Increase conversion Operators: If there is a null value typeSTo non-null typeTThe user-defined type conversion operatorS?ConvertT?. This lifting conversion operator is executed fromS?ToSThe next step isSToTUser-Defined type conversion, and then fromTToT?If it isS?Isnull, Then directly convert to the valuenullOfT?.

Include/be included: IfAType can be implicitly converted (meaning pre-defined type conversion)BType, andAAndBIt is calledA QuiltBInclude, AndB Include A.

Maximum inclusion: In a given type set,Maximum inclusionCan contain all other types in the set. If no type can contain all other types in the Set, there is no type with the highest degree of inclusion. More intuitively, the most inclusive type is the most "extensive" type in the Set-other types can be implicitly converted to it.

Maximum degree of inclusion: In a given type set,Maximum degree of inclusionCan be included by all other types in the set. If no type can be included by all other types in the Set, no type with the highest degree of inclusion exists. More intuitively, the most contained type is the most "precise" type in the Set-it can be implicitly converted to other types.

SlaveSTypeTType User-defined explicit type conversion is handled as follows:

For more information about this algorithm, see UserConversionCache. cs.

Iii. Additional user-defined type conversion

The two methods described above are all fully determined type conversion methods during compilation. The Convert class provides two additional interfaces, which can provide any type conversion method.

AddConverter<TInput, TOutput>(Converter<TInput, TOutput> converter)Methods can register any type of conversion method, andAddConverterProvider(IConverterProvider provider)The method can register the provider of the type conversion method, and batch provide the type conversion method related to a certain type (for example, refer to StringConverterProvider. cs, and provide the type conversion method related to the string ).

Note:: The highest priority is the pre-defined type conversion method and user-defined type conversion method, followedAddConverterMethod registration type conversion method, and thenIConverterProviderOfGetConverterToThe provided type conversion method isIConverterProviderOfGetConverterFromProvides the type conversion method, and the latter has a higher priority.

The complete source code of the content mentioned in this article can be found in Cyjb. Conversions and Cyjb. Reflection.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.