In C # 3.0, almost every new feature is serviced for LINQ. Therefore, this article describes the following new features introduced in C # 3.0:
- Auto-implemented Properties
- Implicitly-typed Local variables
- Object and collection initialization programs
- implicitly-typed arrays
- Anonymous type
In fact, these features are relatively easy to understand, for these features, the compiler helps us do more things (think about anonymous methods and iterator blocks), thus simplifying our code.
Auto-implemented Properties
Before C # 3.0, when we define attributes, we typically use the following code
Public classbook{Private int_id; Private string_title; Public intId {Get{return_id;} Set{_id =value;} } Public stringTitle {Get{return_title;} Set{_title =value;} }}
With the introduction of auto-implemented properties in C # 3.0, the compiler will help us do more transformations, so we can convert the property implementation code above to:
Public class book{ publicintgetset;} Public string Get Set ; }}
After using the auto-implemented properties, the code becomes shorter, and there is no need to define the private fields again.
In fact, when we look at the IL code, we see that the compiler defines the private field and implements the Get/set method.
Note that when using the structure, there is a small problem with the use of automatic attributes: All constructors need to explicitly invoke the parameterless constructor, this (), so that the compiler knows that all the fields are definitely assigned.
For example, in the following code, when we delete ": this ()", the compiler will error.
Public structstudent{ Public intId {Get;Set; } Public stringName {Get;Set; } Public stringGender {Get;Set; } //Use automatic attributes in structs Be sure to call the parameterless constructor explicitly this () PublicStudent (stringName): This() { This. Name =name; }}
Implicitly-typed Local variables
The type systems in C # 1.0 and C # 2.0 are static, display, and secure.
In C # 3.0 we can use the var keyword to define implicitly typed variables, but the variables are still static types, but the compiler can help us infer the type of the variable .
Here's a piece of code that uses an implicitly typed statement that is the same as the Il code for a commented out statement:
Static void Main (string[] args) { var"helloworld"; String str = "Hello world"; var 9; // int num = 9; Console.WriteLine (str. GetType ()); Console.WriteLine (Num. GetType ()); Console.read ();}
As you can see from the output of the code, each implicitly typed variable is a static type (again we can see the type of the implicitly typed variable through vs stepping), where the compiler helped us type inference.
To verify this, but when we assign an integer value to the str variable, we get an error "cannot implicitly convert type ' int ' to ' string '".
Static void Main (string[] args) { var"helloworld"; String str = "Hello world"; 9 ; Console.read ();}
Implicit types of restrictions
With implicit typing, there are some limitations, and not all variables can use implicit types:
- The declared variable is a local variable and cannot be a static field and an instance field
- Variables must be initialized at declaration time
- The compiler needs to infer the type of the variable based on the value of the variable, otherwise a compile-time error occurs
- An initialization expression cannot be a group of methods or an anonymous function (no forced type conversions)
- var Enter = delegate {Console.WriteLine ();};//compilation error
- var enter = (Action) delegate {Console.WriteLine ();};//Normal, because the compiler can do type inference
- Initialization expression is not NULL
- Because null can be implicitly converted to any reference type or nullable type, the compiler cannot do type inference
- Only one variable can be declared in a statement
- "var a = 2, b = 3;" Get a compile error
Advantages and disadvantages of implicit types
Sometimes using implicit typing can reduce the length of code by not affecting the readability of the code, but instead we focus on the more useful code, but there are times when implicit typing is bad for code readability. So it's up to you to measure when you use implicit-type variables. Let's look at a simple example
Static voidMain (string[] args) { //simplified code without sacrificing readability varWordCount =Newdictionary<string,int>(); foreach(varDictinchWordCount) {Console.WriteLine ("Number of {0} is {1}", Dict. Key, Dict. Value); } //poor readability makes it difficult to see variable types directly from your code varNumA =2147483647; varNumB =2147483648; varNUMC =4294967295; Console.WriteLine (Numa.gettype ()); Console.WriteLine (Numb.gettype ()); Console.WriteLine (Numc.gettype ()); Console.read ();}
Implicitly-typed local variable objects and collection initializers
In C # 3.0, we have new methods for object and collection initialization.
Object Initialization Program (initializers)
When we have the object initialization program, the object initialization code becomes more intuitive and simple. See an example:
Public classbook{ Public intId {Get;Set; } Public stringTitle {Get;Set; } //If there is no default constructor, an error occurs when using object initialization PublicBook () {} PublicBook (stringtitle) { This. Title =title; }}classprogram{Static voidMain (string[] args) { //methods for initializing objects before C # 3.0Book B1 =NewBook (); B1. Id=1; B1. Title="C # Step by step"; //using the object initialization programBook B2 =NewBook () {Id =2, Title ="C # in depth"}; Book B3=NewBook {Id =3, Title ="C # in depth" }; Book B4=NewBook ("C # in depth") {Id =1}; }}
When we look at the IL code, we find that the IL codes for B1, B2, and B3 are exactly the same.
Collection Initialization list (collection initializers)
In C # 3.0 It is also proposed to set the initialization list, we can easily implement the initialization of the collection.
Following the example above, we can create a list of books:
//methods for initializing collections before C # 3.0List<book> BookList1 =NewList<book>(); Booklist1.add (B1); Booklist1.add (B2); Booklist1.add (b3); Booklist1.add (b4) ;//using the collection initializerList<book> BookList2 =NewList<book>{b1, b2, B3, B4}; List<Book> BookList3 =NewList<book>{ NewBook{id =5, Title ="Java in Depth"}, NewBook{id =6, Title ="Python in Depth"},};
As you can see, the code becomes more concise after the collection initialization list is used.
By looking at the IL code we can find that when using the Set initialization list, the compiler actually helps us to invoke the Add method of the list element.
implicitly-typed arrays
In C # 1.0 and C # 2.0, when we use arrays, we have to specify the specific array types involved.
In C # 3.0, you can declare and initialize an implicitly typed array by using "new[."
See a simple example:
string[] names = {"Wilber"," would","July" }; Printname (names); Printname (New string[] {"Wilber"," would" });//using an anonymous type array in C # 3.0, the compiler is responsible for inferring the array typePrintname (New[] {"Wilber"," would" });varNameArray =New[] {"Wilber"," would","July" }; Printname (NameArray);//cannot make type inference, compiler error//var array = new[] {1, "Hello World"};...Private Static voidPrintname (string[]names] { foreach(varNameinchnames) {Console.WriteLine (name); }}
Anonymous type
Before C # 3.0, when we created the object, we needed a type. In C # 3.0 There is the concept of anonymous types (similar to anonymous methods, the compiler has done a lot of work for us), and we can define properties for the object directly from the New keyword and assign values to those properties.
See an example:
Static voidMain (string[] args) { //Creating anonymous Objects//Assigning a value to a property through an anonymous object initializer varStudent =New{Name ="Wilber", age = -, Gender ="Male" }; Console.WriteLine ("{0} is {1} years old", student. Name, student. Age); //to initialize a list with an implicitly-typed array varSchool =New[] { //create an instance using the same anonymous type New{Name ="Wilber", Gender ="Male", age = - }, New{Name =" would", Gender ="Male", age = - }, New{Name ="Lily", Gender ="Female", age = - }, }; intTotalage =0; foreach(varStuinchSchool) {Totalage+=Stu. Age; } Console.WriteLine (Totalage); Console.read ();}
In the example above, we can look at the IL code to see what the compiler has done for us.
With Ilspy we can see that for anonymous types in C # code, the compiler helped us generate a specific anonymous type of "<>F__ANONYMOUSTYPE0 ' 3" and "<>f__anonymoustype1 ' 3".
note that although the anonymous type of the student variable is instantiated <name, age, Gender>, and the anonymous type that instantiates the school array element <name, Gender, age> Only the order of the attributes is different, and the compiler treats them as two distinct types.
Summarize
Some of the features presented in C # 3.0 are described in this article, although these features are best prepared for LINQ, but they can also be used alone to simplify our code.
Understanding implicit types, object initializers, and anonymous types