Home PC Games Linux Windows Database Network Programming Server Mobile  
           
  Home \ Programming \ Deep understanding of C # generics     - Hard disk encryption to protect data security (Linux)

- Getting the Linux shell variable test (Programming)

- What factors affect the performance of Java calls (Programming)

- C language sorting instance (select, bubble, insert, binary, fast) (Programming)

- Linux Command Line Art (Linux)

- Sublime Text 3 shortcuts summary (Linux)

- Effect MongoDB plan cache (Database)

- Build your own CA services: OpenSSL command line CA Quick Guide (Server)

- Debian 7 and Debian 8 users how to install Oracle Java 8 (Linux)

- Ubuntu and Archlinux install Notepadqq 0.50.2 (Linux)

- Generated characters using Java Videos (Programming)

- CentOS7 iptables (Linux)

- Spark On YARN cluster installation deployment (Server)

- Three kinds of implementation model of the Linux thread history (Programming)

- CentOS 7 Test Marathon start Docker container (Server)

- CentOS 6.6 permanent method to modify the DNS address (Linux)

- Linux Log File Browser --logrotate (Linux)

- AngularJS achieve picture upload feature (Programming)

- Bash common several configuration files (Linux)

- Linux directory permissions to read and execute permissions difference (Linux)

 
         
  Deep understanding of C # generics
     
  Add Date : 2017-08-31      
         
         
         
  Generic internal mechanism

Generics have type parameters, which provide a "parameterized" type via type parameters. In fact, the "type parameter" of the generic type becomes a generic type of metadata, and the "runtime" takes advantage of them when needed Constructing the appropriate types, through which we can instantiate different types of objects. That is, an unbound generic type is a blueprint that constructs a generic type, a generic type, and an actual object.

Analyze generic IL code

Consider an example in which a generic class for comparison and a non-generic class for comparison int are defined in this example:

Namespace GenericTest
{
    Class CompareUtil < T> where T: IComparable
    {
        Public T ItemOne {get; set;}
        Public T ItemTwo {get; set;}

        Public CompareUtil (T itemOne, T itemTwo)
        {
            This.ItemOne = itemOne;
            This.ItemTwo = itemTwo;
        }}

        Public T GetBiggerOne ()
        {
            If (ItemOne.CompareTo (ItemTwo)> 0)
            {
                Return ItemOne;
            }}
            Return ItemTwo;
        }}
    }}

    Class IntCompareUtil
    {
        Public int ItemOne {get; set;}
        Public int ItemTwo {get; set;}

        Public IntCompareUtil (int itemOne, int itemTwo)
        {
            This.ItemOne = itemOne;
            This.ItemTwo = itemTwo;
        }}

        Public int GetBiggerOne ()
        {
            If (ItemOne.CompareTo (ItemTwo)> 0)
            {
                Return ItemOne;
            }}
            Return ItemTwo;
        }}
    }}

    Class Program
    {
        Static void Main (string [] args)
        {
            CompareUtil < int> compareInt = new CompareUtil < int> (3, 6);
            Int bigInt = compareInt.GetBiggerOne ();

            IntCompareUtil intCompareUtil = new IntCompareUtil (4, 7);
            Int big = intCompareUtil.GetBiggerOne ();

            Console.Read ();
        }}
    }}
}}

First of all, ILSpy look at the generic class "CompareUtil < T>" IL code (only listed a part of the IL code)

.class private auto ansi beforefieldinit GenericTest.CompareUtil`1 < ([mscorlib] System.IComparable) T>
    Extends [mscorlib] System.Object
{
...
.method public hidebysig specialname rtspecialname
        Instance void .ctor (
            ! T itemOne,
            ! T itemTwo
        ) Cil managed
    {...}
    ...
    // Properties
    .property instance! T ItemOne ()
    {
        .get instance! 0 GenericTest.CompareUtil`1 :: get_ItemOne ()
        .set instance void GenericTest.CompareUtil`1 :: set_ItemOne (! 0)
    }}
    .property instance! T ItemTwo ()
    {
        .get instance! 0 GenericTest.CompareUtil`1 :: get_ItemTwo ()
        .set instance void GenericTest.CompareUtil`1 :: set_ItemTwo (! 0)
    }}

} // end of class GenericTest.CompareUtil`1
Copy the code
You can see that the IL code for a generic class is basically the same as the IL code for a non-generic class, except that there is some type parameter metadata in the IL class of the generic class.

Here's a look at some of the special points in the generic IL code:

GenericTest.CompareUtil`1 < ([mscorlib] System.IComparable) T>
`1 'represents the number of elements, which is the number of type parameters
< ([Mscorlib] System.IComparable) T> is the type constraint we add to the generic type
! T and! 0
! T is a placeholder for the type parameter
! 0 represents the first type parameter (when the generic meta-number is 2,! 1 represents the second type parameter)
At the same time, we can also compare the generic and non-generic class instance of IL code

IL_0003: newobj instance void class GenericTest.CompareUtil`1 < int32> ::. Ctor (! 0,! 0)

IL_0012: newobj instance void GenericTest.IntCompareUtil ::. Ctor (int32, int32)

Generic mechanism

According to the above analysis can be obtained, C # generic CLR at the run-time support capabilities, the compiler in dealing with the time to do two things:

When the compiler encounters a generic code such as "CompareUtil < T>", the compiler uses special placeholders to represent the type parameters when compiling generic code into IL code and metadata
While the actual generic instantiation work in the "on-demand" approach, that is when the compiler encountered "CompareUtil < int> compareInt" specified type parameters of the code, according to the type parameter JIT will be generic type IL translates to native code, which already uses the actual data type, equivalent to the class declared with the actual type
Instantiation of value types and reference types

The JIT generates the same native code for all generic types whose type is "reference type". This is done because all the references have the same size.

However, if the type parameter is a "value type", JIT will generate a separate native code for each of the different "value types".

As for why the use of generic types can be avoided value boxing and unboxing operation:

List < int> intList = new List < int> ();
I believe we see the following IL code to understand, in the generic category, are directly through the use of type parameters type.

// Fields
.field private! T [] _items
Use typeof for generic types

In C #, we often use typeof operator to get a System.Type object reference.

For generic types, we can also use typeof in two ways:

Get a generic type definition (unbound generic type)
In order to obtain the definition of generic types, only need to provide the type name of the statement, delete all types of parameters, but keep the comma
Gets a specific constructed type (that is, a type reference that gets a closed type)
You only need to specify a type argument
The following look at a simple example,

Static void DemonstrateTypeOf < T> ()
{
    Console.WriteLine (typeof (T));

    Console.WriteLine (typeof (List < >));
    Console.WriteLine (typeof (Dictionary < ,>));

    Console.WriteLine (typeof (List < T>));
    Console.WriteLine (typeof (Dictionary < string, T>));

    Console.WriteLine (typeof (List < long>));
    Console.WriteLine (typeof (Dictionary < string, int>));
}}
The output of the function is as follows:

System.Double
System.Collections.Generic.List`1 [T]
System.Collections.Generic.Dictionary`2 [TKey, TValue]
System.Collections.Generic.List`1 [System.Double]
System.Collections.Generic.Dictionary`2 [System.String, System.Double]
System.Collections.Generic.List`1 [System.Int64]
System.Collections.Generic.Dictionary`2 [System.String, System.Int32]
From the output, we can also see the type of each generic meta, as well as the generic types (unbound generic types and enclosing types).

Static fields and static constructors

A static field in a generic

In C #, static member variables of a class are shared between different class instances, and can be accessed by class names. C # 2.0 introduced generics, resulting in static member variables of the mechanism there have been some changes: static member variables in the same closed type of sharing between different closed types are not shared. This is also very easy to understand, because different types of closure have the same class name, but because of the different data types were introduced, they are completely different types.

Look at a simple example:

Namespace GenericTest
{
    Class TypeWithField < T>
    {
        Public static string field;
        Public static void PrintField ()
        {
            Console.WriteLine (field);
        }}
    }}

    Class Program
    {
        Static void Main (string [] args)
        {
            TypeWithField < int> .field = "Int Field";
            TypeWithField < string> .field = "String Field";

            TypeWithField < int> .PrintField ();
            TypeWithField < string> .PrintField ();

            Console.Read ();
        }}
    }}
}}
Static constructors in generics

Static constructor rules: only one, and can not have parameters, he can only be. NET runtime call automatically, but can not be manually called, and can only be executed once.

Generics of the static constructor of the principle and non-generic class is the same, just differentiate the generic type of closure can be understood as different classes.
     
         
         
         
  More:      
 
- Configure the Linux kernel and use iptables to do port mapping (Linux)
- Protection Docker container Notice (Server)
- To convert into a binary search tree sorted doubly linked list (Programming)
- Linux operating system ARP Spoofing Defense (Linux)
- PHP Performance Analysis and Experiment: Performance Micro Analysis (Programming)
- Install Redis 2.6 5.5 32 position CentOS error resolved (Linux)
- Whisker Menu 1.4.3 Install menu Linux (Linux)
- Oracle database physical file backup / restore (Database)
- Linux 4.0+ kernel support for hardware switching module (HW Switch Offload) (Linux)
- Linux under DB2SQL1024N A database connection does not exist. SQLS (Database)
- Use XtraBackup to MySQL database online incremental backup and recovery (Database)
- Oracle TAF Analysis (Database)
- Google open source TCP team repaired the Linux kernel TCP flaw (Linux)
- Close Pycharm spell check (Programming)
- 11G ASM disk group does not automatically handle MOUNT (Database)
- Ubuntu 12.04 LTS installation configuration JDK1.6.0_45 (Linux)
- Ubuntu installation 2.10.x version of Scala (Linux)
- Linux System Getting Started Learning: Repair fatal error openssl aes h no such file or directory (Linux)
- Disk storage structure and file recovery experiment (FAT file system) (Linux)
- Netcat Example (Linux)
     
           
     
  CopyRight 2002-2022 newfreesoft.com, All Rights Reserved.