After the introduction of the previous topic, you should have a better understanding of the features in C #1 and C #2. Now we have finally ushered in the long-awaited special feature in C #3, in C #, Lambda expressions and the proposal of Linq are equivalent to completely changing our encoding style. Some beginners will find it hard to understand them at the beginning, but I believe that, you will love all the features in C #3 after studying and understanding it, because I did it myself. At this time last year, when I saw Lambda expressions and Linq, I felt very difficult to understand and felt very strange (because I used to write code with features earlier than C #3, although the features in C #3 have been coming out for a long time, they are rarely written and have not been studied, so I feel very strange, there is a feeling: How can I write it like this ?), After studying the C # language system during this period, we found that new features are based on previous features, but now the compiler will help us parse the features proposed in C #3, so for the compiler, the code written with the features in C #3.0 is the same as the code written in C #2.0. Starting from this topic, we will introduce the features in C #3. This topic will introduce some basic features proposed in C #3, these features are also the basis of Lambda expressions and Linq. 1. automatically implemented attributes when the attributes defined in the class do not require some additional verification, we can use the automatically implemented attributes to make the attribute definition more concise, for an attribute automatically implemented in C #3, the compiler creates a private anonymous field during compilation. This field can only be accessed through the get and set accessors of the attribute. The following is an example of an attribute automatically implemented in C #3: /// <summary> /// custom class /// </summary> when we define attributes before public class Person {// C #3, it is usually like the following to define // first, the private field is defined, and then the attribute is defined to access the field // private string _ name; // public string Name // {// get {return _ name;} // set {_ name = value ;} //} // after C #3, attributes are automatically implemented. // For attributes that do not require additional verification, you can use the automatically implemented attribute to simplify the attribute definition. // No additional private field is required. // The private field is not defined at this time, the compiler only helps us generate an anonymous private field. We do not need to write/reduce the code we write in the code. To define an attribute. The effect is equivalent to the definition of the attribute above, however, it is more concise than before. // <summary> // Name // </summary> public string Name {get; set ;} /// <summary> /// Age /// </summary> public int Age {get; private set ;} /// <summary> /// custom constructor /// </summary> /// <param name = "name"> </param> public Person (string name) {Name = name ;}some may ask -- how do you know that the compiler will generate an anonymous private field for us? Of course, the reflection tool is used to view the Code Compiled by the compiler. The following is a Reflector tool: If Automatic attributes are used in the struct, then, all constructors must call the non-argument constructor this () explicitly. Otherwise, a compilation error occurs, because only the non-argument constructor this () is explicitly called (), the compiler knows that all fields are assigned values. The following is a test code: /// <summary> /// use automatic attributes in the struct /// </summary> public struct TestPerson {// automatic attributes public string Name {get; set ;} // In the structure, all constructors must explicitly call the non-parameter constructor this (). // otherwise, a compilation error may occur. // only the non-parameter constructor is called, the compiler knows that all fields are assigned public TestPerson (string name) //: this () {this. name = name;} after you comment out this (), a compilation error occurs, for example:
2. If the implicit type is a variable defined by the keyword var, the variable is of the implicit type. The var keyword tells the compiler to deduce the type of the variable based on the value class of the variable. Therefore, for the compiler, the implicit type is also explicit and also has an explicit type. 2.1 implicit local variables use the var keyword to declare local variables. The following Code demonstrates static void Main (string [] args) {// use var to declare the local variable var stringvariable = "learning hard"; stringvariable = 2;} Why does the variable defined with var still have an explicit type for the compiler? In Visual studio, when you move the mouse over the var part, you can see that the compiler is the type of variable inference. And the variable is still a static type, but we didn't write the type name in the Code. This task is handed over to the compiler to deduce the type of the variable based on the value of the variable, to prove the static type of a variable, a compilation error occurs when we assign 2 to the variable stringvariable. However, in other dynamic languages, such assignments can be compiled, so the variables declared with var are still static, but we haven't written them in the code. The following is the proof of the above two points: however, there are some restrictions when using implicit types. Specific restrictions include: the declared variable is a local variable and cannot be a field (including static fields and instance fields) variables must be initialized during Declaration (because the compiler must deduce the type of the Variable Based on the Value assignment of the variable. If the variable is not initialized, the compiler cannot deduce the variable type, however, if C # Is a static language, you must specify the type of the variable when defining the variable. Therefore, if the variable does not know the type, a compile-time error will occur) variable initialization cannot be a method group or an anonymous function (provided that no forced type conversion is performed) variable cannot be initialized to null (because null can be implicitly converted to any reference type or empty type, the compiler cannot deduce the type of the variable) you cannot use a declared variable to initialize the implicit type (for example, you cannot declare the implicit type like this). // you cannot use an unassigned variable to initialize the private type. // If the variable s is initialized you can use string s; var stringvariable = s;) The var cannot be used. The parameter types in the explicit method have both advantages and disadvantages when using the implicit type. The following sample code fully interprets the advantages of the implicit type. // for complex types, reduce the typing volume // use the implicit type. In this case, you do not need to specify the left and right sides of the value to specify Dictionary <string, string> var dictionary = new Dictionary <string, string> (); // use the implicit type foreach (var item in dictionary) in foreach) {//} // downsides of the implicit type // the following code uses the implicit type, which makes it difficult for developers to know the specific type of the variable // so when the implicit type is used, it depends entirely on your personal situation. If you feel that the implicit type is used, it will make the Code look more neat and easy to understand. var a = 2147483649; var B = 928888888888; var c = 2147483644; Conso Le. writeLine ("variable a type: {0}",. getType (); Console. writeLine ("type of variable B: {0}", B. getType (); Console. writeLine ("variable c type: {0}", c. getType (); Console. read (); 2.2 implicit array var can not only create Partial Variables of the implicit type, but also create arrays. The following is a Demo code: // implicit type array demonstration // the compiler can infer the int [] type var intarray = new [] {1, 2, 4 }; // The Compiler inferred to be string [] var stringarray = new [] {"hello", "learning hard "}; // var errorarray = new [] {"hello", 3} When an error occurs in the implicit type array; use the number of implicit types When grouping, the compiler must deduce the type of array used. The Compiler first constructs all expressions containing braces (such as 1, 2, 3, 4, and "hello" in the code above ", "learning hard"). If all types in this set can be implicitly converted to a sweater type, this type will become the array type. Otherwise, an error occurs during compilation. For example, if an error occurs in an implicit array of type in the code, because "hello" is converted to string, but 3 is converted to int, in this case, the compiler cannot determine the type of the array, so a compilation error occurs. The error message is: "The optimal type of the implicit type array is not found." 3. object set initialization 3.1 after the object initialization feature is enabled, we don't need to consider defining constructors with different parameters to cope with initialization in different situations, so we can reduce the constructor code defined in our object classes, which makes the code more concise, the following describes how to use and pay attention to object initialization in C #3: Demo {class Program {static void Main (string [] args) {# region object initialization demonstration // before C #3.0, we may use the following method to initialize the object Person person1 = new Person (); person1.Name = "learning hard"; person1.Age = 25; Person person2 = new Person ("learning hard "); person2.Age = 25; // if the class has no constructor without parameters, a compile-time error will occur. // The following statement calls the constructor without parameters to initialize fields in the class. // braces is the object initialization program Person person3 = new Person {Name = "learning hard ", age = 25}; // the following code is equivalent to the above Code, except that People person4 = new Person () {Name = "learning hard", Age = 25}; Person person5 = new Person ("learning hard ") {Age = 25 }; # endregion }}/// <summary> // custom class // </summary> public class Person {// <summary> // name /// </summary> public string Name {get; set ;}/// <summary >/// Age /// </summary> public int Age {get; set ;} /// <summary> /// define a constructor without parameters /// if a constructor with parameters is defined in the class, No default constructor is generated during compilation. // if no default constructor exists, when the object is initialized, an error is reported indicating that no constructor without parameters is implemented. // </summary> public Person () {}/// <summary> /// custom constructor /// </summary> /// <param name = "name"> </param> public Person (string name) {Name = name ;}} in the above code, I marked in red what should be noted during object initialization, you can also use the reflection tool to check how the compiler parses the object initialization code. 3.2 set initialization C #3 also proposes the set initialization feature to optimize the set initialization. The following is a Demo code for using the set initialization: namespace object collection initiator Demo {class Program {static void Main (string [] args) {# region collection initialization demo/C # code List used to initialize the collection before 3.0 <string> names = new List <string> (); names. add ("learning hard1"); names. add ("learning hard2"); names. add ("learning hard3"); // with the C #3.0 integration initialization feature, you can simplify the code // the implicit type is also used below (using the var keyword) var newnames = new List <string> {"learning ha Rd1 "," learning hard2 "," learning hard3 "}; # endregion }}/// <summary> // custom class // </summary> public class Person {// <summary> // name /// </summary> public string Name {get; set ;}/// <summary >/// Age /// </summary> public int Age {get; set ;} /// <summary> /// define a constructor without parameters /// if a constructor with parameters is defined in the class, no default constructor is generated during compilation. // if no default constructor exists, when the object is initialized, an error is reported, indicating that no constructors without parameters are implemented. // </summary> public Person () {}/// <su Mmary> /// custom constructor /// </summary> /// <param name = "name"> </param> public Person (string name) the {Name = name ;}} set Initialization is also automatically used by the compiler to help us call the List's no-argument constructor and then Add the Add () method one by one. For the compiler, the code for using the set initialization in C #3 is the same as the code written before C #3. however, for developers, after the C #3 set is initialized, this process does not need to be encoded by ourselves, but is just for the compiler to help us, to prove what the compiler has done for us, let's look at the reflection tool to see how the compiler has helped us translate the initialization of the Set: list <string> names = new List <string> (); names. add ("learning hard1"); names. add ("learning ha Rd2 "); names. add ("learning hard3"); List <string> <> g _ initLocal3 = new List <string> (); <> g _ initLocal3.Add ("learning hard1 "); <> g _ initLocal3.Add ("learning hard2"); <> g _ initLocal3.Add ("learning hard3"); List <string> newnames = <> g _ initLocal3; from the Code reflected above, we can see that the compiler is indeed a good guy who has done so many things for us. You may have such a question: object set Initialization is just a syntactic sugar, that is, let us write less code, and there is no other use? The following sections will solve your questions. 4. When you see the anonymous type, you may think of the anonymous method described earlier. The compiler uses the same processing method for both the anonymous type and the anonymous method, this method generates a type name for the compiler for the anonymous type. We do not need to explicitly customize a type in the Code. The following describes how to use the anonymous type: namespace anonymous Demo {class Program {static void Main (string [] args) {# Demo of the region anonymous type // defines the anonymous type // because the initialization type is unknown here, therefore, the implicit type must be used here. // at this time, the implicit type plays an indispensable role, this shows that the implicit type is proposed to serve the anonymous type // while the anonymous type is proposed to serve the Linq, and is step by step controlled by the Microsoft team's plan. writeLine ("demo for entering the anonymous type:"); var person1 = new {Name = "learning hard", Ge = 25}; Console. writeLine ("{0} age: {1}", person1.Name, person1.Age); Console. read (); Console. writeLine ("press Enter to Enter an anonymous array Demo:"); Console. writeLine (); # endregion # region anonymous array demo // defines an anonymous array var personcollection = new [] {new {Name = "Tom", Age = 30 }, new {Name = "Lily", Age = 22}, new {Name = "Jerry", Age = 32 }, // if the following sentence is added, a compile-time error may occur. // at this time, the compiler cannot infer why the conversion type is required. // new {Name = "learning hard "}}; int totalAge = 0; foreach (var person in personcollection) {// the following code proves that the Age attribute is of the strong int type totalAge + = person. age;} Console. writeLine ("Total Age of all: {0}", totalAge); Console. readKey (); # endregion }}} running result: all the features described in the previous sections-implicit type and object set initialization were used in the anonymous demonstration above, therefore, you can also obtain the answer to the question that object set Initialization is of no other use. If there is no object set initialization, is it possible to write such code (var person1 = new {Name = "learning hard", Age = 25? Therefore, another use of the previous implicit type and object set Initialization is to serve the anonymous type. However, the anonymous type serves the Linq, and there are numerous advantages for the Linq at the time, we will introduce you to the following topics. The above also pointed out that although we do not specify a type name for the anonymous type in the Code, the compiler will generate a type for us, to prove this, we also use the reflection tool Reflector to check what the compiler finally generates for us? As follows:
From the above, we can see that the compiler indeed generates an anonymous type for us.) <> f _ AnonymousType0 <Name> j _ TPar, <Age> j _ TPar> (the code is equivalent to the Person class defined above). The type generated by the compiler for us is directly inherited from System. object and internal sealed (this type is visible only in the Assembly and cannot be inherited ). 5. Here, the introduction of this topic is over, this topic introduces several basic features in C #3: automatically implemented attributes, implicit types, object set initialization, and anonymous types, these types are proposed to serve the more complex features of Linq. Therefore, only by mastering these basic features can you better master the basics of Linq. In the next topic, we will talk about the Lambda expressions in C #3.