C # Generics In-depth understanding Introduction _c# Tutorial

Source: Internet
Author: User
Tags mscorlib static class
Introduction:

The previous topic described the reasons for introducing generics in c#2.0 and the benefits of generics, but the previous topic was equivalent to introducing some of the basics of generics, and there was no justification for the performance of generics over Non-generic performance. So the reason and some other knowledge about generics will be presented on this topic.

first, generic type and type parameters

Generic types are the same type as other int,string, and there are two manifestations of generic types: generic types (including classes, interfaces, delegates, and structs, but no generic enumerations) and generic methods. What kinds of classes, interfaces, delegates, and methods are called generic types? My understanding is that a class, interface, delegate, struct, or method has a type parameter that is a generic type, and thus has the concept of a type parameter. Type parameter--is a placeholder for a real type (I think of a very figurative metaphor, for example, when you are in school, one to noon when the canteen is very many people, so many should be useful books occupy the habit of position, the book is equivalent to a placeholder, really sit in the position of course is their own, Talk about the position, before I heard my classmate said that their class has a very good mm, at the end of the afternoon when the class with mobile phone occupy a seat, and so it came back when the phone has disappeared, at that time after listening to me and my classmate said, your class this girl really good, behind us on), the generic Declaration, The type parameter must be placed inside a pair of angle brackets (that is, the <> symbol), and a comma separates multiple type arguments, such as the type parameter in the List<t> class, and when using a generic type or method, we replace it with a real type, just as a book occupies a seat, The book is only temporary in that position, when the meal is ready to replace you sit in the position, also in C # generics are the same reason, the type parameter is only temporary in that position, really use the real type to replace its position, at this time we have the real type is named type argument, As in the previous topic's code, the type argument is the int (in place of T). List<int&gt

If a type argument is not supplied for the type parameter, at this point we declare an unbound generic type, and if the type argument is specified, then the type is called a constructed type (which can also be understood in place of the book), whereas a constructed type can be an open type or a closed type. Here we first give the definition of the two concepts: open type-types with type parameters are open types (all unbound generic types are of open type), enclosing type--the actual data type is passed for each type parameter. For open types, we create an instance of an open type.

Note:In C # code, the only place where we can see the unbound generic type (except as a declaration) is in the TypeOf operator.

Here's a better illustration of this by using the following code:
Copy Code code as follows:

Using System;
Using System.Collections.Generic;

Namespace Closetypeandopentype
{
Declaring an open generic type
public sealed class Dictionarystringkey<t>: Dictionary<string, t>
{

}

public class Program
{
static void Main (string[] args)
{
Object o = null;

Dictionary<,> is an open type, it has 2 type parameters
Type t = typeof (Dictionary<,>);

Create an instance of an open type (creation fails, exception occurs)
o = CreateInstance (t);
Console.WriteLine ();

Dictionarystringkey<> is also an open type, but it has 1 type parameters
t = typeof (Dictionarystringkey<>);

Creates an instance of the type (also fails with an exception)
o = CreateInstance (t);
Console.WriteLine ();

Dictionarystringkey<int> is a closed type
t = typeof (Dictionarystringkey<int>);

Create an instance of the enclosing type (successful)
o = CreateInstance (t);

Console.WriteLine ("Object type =" + O.gettype ());
Console.read ();
}


Create type
Private static Object CreateInstance (Type t)
{
Object o = null;
Try
{
Creates an instance of the type using the default constructor of the specified type T
o = activator.createinstance (t);
Console.WriteLine ("Instance of {0} created", t.tostring ());
}
catch (Exception ex)
{
Console.WriteLine (ex. message);
}

return o;
}
}
}

The run result is (you can also see from the results that an open type cannot create an instance of that type, which indicates that the type contains generic parameters):


static fields and static constructors in generic types

First, the instance fields belong to an instance, and the static fields are of the type declared by them, that is, if a static fields field is declared in a MyClass class, no matter how many instances of the MyClass are created, or how many instances derive from the MyClass, There is only one myclass.x field. However, each enclosing type has its own static field (when the type argument is used, in fact, the CLR defines a new type object, so each static field is a static field in a different object, so each has its own value, which is better illustrated by the following code: Each enclosing type has its own static field:

Copy Code code as follows:

View Code

Namespace Genericstaticfieldandstaticfunction
{
Generic class, with a type parameter
public static Class Typewithstaticfield<t>
{
public static string field;
public static void Outfield ()
{
Console.WriteLine (field+ ":" +typeof (T). Name);
}
}

Non-generic class
public static Class Nogenerictypewithstaticfield
{
public static string field;
public static void Outfield ()
{
Console.WriteLine (field);
}
}
Class Program
{
static void Main (string[] args)
{
When a type argument is used, the CLR actually defines a new type object
So each static field is not the same as the static field inside the object, so each has its own value
Assigning a static field to a generic type class
Typewithstaticfield<int>.field = "one";
Typewithstaticfield<string>.field = "two";
Typewithstaticfield<guid>.field = "three";

At this point the filed value will have only one value, and each assignment is changing the original value.
Nogenerictypewithstaticfield.field = "non-generic class static field one";
Nogenerictypewithstaticfield.field = "non-generic class static field two";
Nogenerictypewithstaticfield.field = "non-generic class static field three";

Nogenerictypewithstaticfield.outfield ();

Prove that each enclosing type has a static field
Typewithstaticfield<int>. Outfield ();
Typewithstaticfield<string>. Outfield ();
Typewithstaticfield<guid>. Outfield ();
Console.read ();

}
}
}

Run Result:

Also, each enclosing type has a static constructor, and the following code can make this more clear:
Copy Code code as follows:

Examples of static constructors
public static Class Outer<tx>
{
Nested classes
public class Inner<ty>
{
Static constructors
Static Inner ()
{
Console.WriteLine ("OUTER<{0}> Inner<{1}> ", typeof (Tx), typeof (Ty));
}

public static void Print ()
{
}
}
}
Class Program
{
static void Main (string[] args)
{
Demonstration of #region static function

Static constructors Run multiple times
Because each enclosing type has a separate static constructor
Outer<int>. Inner<string>. Print ();
Outer<int>. Inner<int>. Print ();
Outer<string>. Inner<int>. Print ();
Outer<string>. Inner<string>. Print ();
Outer<object>. Inner<string>. Print ();
Outer<object>. Inner<object>. Print ();
Outer<string>. Inner<int>. Print ();
Console.read ();
#endregion
}
}

Run Result:

The results from the above diagram may find that 7 of our code needs to be output, but only 6 results are output in the result, because the static constructor of any enclosing type executes only once, the last line of Outer<string>. Inner<int>. Print (); This line does not produce line 7th output because of the outer<string>. Inner<int>. The static constructor of Print () was previously executed (the third row has already been executed).
iii. how the compiler resolves generics

In the previous topic, I just posted a comparison between generics and Non-generic to illustrate the benefits of generics with high performance, but did not give a specific reason for the high efficiency of generics than non-generic, so in this section to analyze the specific reasons for generic efficiency.

Here's the code that illustrates the generics high performance benefit in the previous topic, and then the IL code to illustrate the high performance of generics (how the C # compiler resolves to Il code for generics and Non-generic):
Copy Code code as follows:
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

Namespace Generaldemo
{
public class program
{
static void Main (string[] args)
{
Stopwatch stopwatch = new stopwatch ();

//non-generic array
ArrayList ArrayList = new ArrayList ();

///generic array
list<int> genericlist= new list<int> ();

//start timer
Stopwatch. Start ();
for (int i = 1; i < 10000000; i++)
{
//genericlist. ADD (i);
ArrayList. ADD (i);
}

//End Timings
Stopwatch. Stop (); The time used by the

//output
TimeSpan ts = stopwatch. Elapsed;
String elapsedtime = String.Format ("{0:00}:{1:00}:{2:00}.{ 3:00} ",
ts. Hours, TS. Minutes, TS. Seconds,
TS.MILLISECONDS/10);
Console.WriteLine ("Run Time:" + elapsedtime);
Console.read ();
}
}
}

When using a non-generic ArrayList array, the IL's Code is as follows (here is just a partial central code posted, and you can download the sample source from the Il disassembly program):
Copy Code code as follows:

Il_001f:ldloc.1
Il_0020:ldloc.3
Il_0021:box [Mscorlib]system.int32
Il_0026:callvirt instance Int32 [Mscorlib]system.collections.arraylist::add (Object)
Il_002b:pop
Il_002c:nop
Il_002d:ldloc.3
il_002e:ldc.i4.1
Il_002f:add

In the IL code above, my code with the red markup is mainly in the execution of boxing operations (the boxing process is definitely going to consume the event of the bar, like a parcel in life, packing must take a certain amount of time, the boxing operation will also, however, for generic types can avoid boxing operations, The following is a screenshot of the IL code using the generic type-this operation is also the root cause of the performance of non-generic types that are not as generic. But why use the ArrayList type before calling the Add method to add elements to an array? The reason is actually mainly in the Add method, you can use the reflector reflection tool to view the ArrayList Add method definition, the following is a screenshot of the Add method prototype:

As you can see from the screenshot above, ADD (objec value) needs to receive parameters of type object, but we need to pass an int argument in our code, and then we need a boxing operation (the value type int is converted to an object reference type, which is a boxing operation), This also explains why the call to the Add method performs a boxing operation and also shows the benefits of the high performance of generics.

The following is a screenshot of the IL code using the generic list<t> (as you can see from the picture, the boxed operation is not performed when using generics, so there is less time to box, so of course it runs faster and performance is good.) ):

Iv. Summary

Speaking of which, the contents of this topic are also concluded. This topic is mainly to further introduce the generics of other content, due to the length of the other content of the generics in the next topic, if the content in this topic will appear very much, which is not conducive to the digestion and everyone reading, So I'll continue to introduce some of the other aspects of generics in the next topic.

The following is a list of all the demo source code used in the generic topic: Generaldemo_jb51.rar

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.