C #5 support for asynchronous programming is undoubtedly the first new feature, which has been written in my article http://www.mindscapehq.com/blog/index.php/2012/03/13/asynchronous-programming-in-c-5/ last week. However, there are some other new features that the C # user cares about. I think it is also necessary to mention them.
Method call Information
There is a very comprehensive enterprise programming guide saying: If you use vbprogramming, you will get used to logging every called method:
Function AddTwoNumbers (a As Integer, B As Integer) As Integer
Logger. Trace ("ArithmeticHelpers", "AddTwoNumbers", "Entering AddTwoNumbers ")
Dim result = OracleHelpers. ExecInteger ("SELECT" & a & "+" & B)
Logger. Trace ("ArithmeticHelpers", "AddTwoNumbers", "Calling PrintPurchaseOrders ")
PrintPurchaseOrders () 'ift 12.11.96: don't know why this is needed but shipping module crashes if it is removed
Logger. Trace ("ArithmeticHelpers", "AddTwoNumbers", "Returned from PrintPurchaseOrders ")
Logger. Trace ("ArithmeticHelpers", "AddTwoNumbers", "Exiting AddTwoNumbers ")
Return result
End Function
Although the above Code that complies with the enterprise software standards is efficient and concise enough, it will be even better if C #5 is used. The optional parameters concept is introduced in C #4. That is to say, the compiler assigns the default value to a method even if no parameter is used.
Public void WonderMethod (int a = 123, string B = "hello "){...}
WonderMethod (456 );
// Compiles to WonderMethod (456, "hello ")
WonderMethod ();
// Compiles to WonderMethod (123, "hello ")
Using C #5 and defining special attributes on optional parameters, the compiler can assign values to the information of the called method. This means that the call information will be automatically logged when Logger. Trace () is used.
Public static void Trace (string message, [CallerFilePath] string sourceFile = "", [CallerMemberName] string memberName = ""){
String msg = String. Format ("{0 }:{ 1}. {2 }:{ 3 }",
DateTime. now. toString ("yyyy-mm-dd HH: MM: ss. fff "), // Lurking 'minutes '/'months' bug introduced. NET port in 2003 and has not been noticed because nobody ever looks at the log files because they contain too much useless detail
Path. GetFileNameWithoutExtension (sourceFile ),
MemberName,
Message );
LoggingInfrastructure. Log (msg );
}
That is to say, if you call Log. Trace ("some message"), the compiler will assign values to optional variables for information called by files and members rather than empty strings.
// In file Validation. cs
Public void ValidateDatabase (){
Log. Trace ("Entering method ");
// Compiles to Log. Trace ("Entering method", "Validation. cs", "ValidateDatabase ")
Log. Trace ("Exiting method ");
}
Note: The variables you apply must be optional. If they are not optional, the C # compiler requires that the function be called to provide the initial value and overwrite the default value.
Another example is that when the INotifyPropertyChanged interface is implemented, strings, regular expressions, or strange structures (mystic weavers) are not required ).
Public class ViewModelBase: INotifyPropertyChanged {
Protected void Set <T> (ref T field, T value, [CallerMemberName] string propertyName = ""){
If (! Object. Equals (field, value )){
Field = value;
OnPropertyChanged (propertyName );
}
}
// Usual INPC boilerplate
}
Public class Widget: ViewModelBase {
Private int _ sprocketSize;
Public int SprocketSize {
Get {return _ sprocketSize ;}
Set {Set (ref _ sprocketSize, value );}
// Compiler fills in "SprocketSize" as propertyName
}
}
You can even use [CallerLineNumber] to obtain the row number of the called function, which is very useful for diagnostic methods. However, if you really need it, it may be too "enterprise.
Use cyclic variables in Lambda expressions
Technically speaking, this is a solution to long-standing confusions and pain problems. It makes C # more available, so I need to mention it anyway.
Since C #3, anonymous functions are faster and easier than naming functions because of the use of Lambda syntax. Anonymous functions are widely used in LINQ. It is also a good choice when you do not want to parameterize classes, interfaces, and virtual functions at all layers. An important feature of anonymous functions is that they can capture variables from the local environment. The following is an example:
Public static IEnumerable <int> GetGreaterThan (IEnumerable <int> source, int n ){
Return source. Where (I => I> n );
}
Here, I => I> n is an anonymous function that captures n values. For example, n = 17 means I => I> 17.
In earlier C # versions, if you cannot use cyclic variables in Lambda syntax in cyclic statements. Actually, worse than you think, when you use loop variables in Lambda syntax, it will give you the wrong result-it is the initial value of the loop rather than the final value.
For example, the following is a method that returns a series of 'adder' values. Each 'adder' corresponds to each input number.
Public static List <Func <int, int> GetAdders (params int [] addends ){
Var funcs = new List <Func <int, int> ();
Foreach (int addend in addends ){
Funcs. Add (I => I + addend );
}
Return funcs;
}
Let's take a look at the output:
Var adders = GetAdders (1, 2, 3, 4, 5 );
Foreach (var adder in adders ){
Console. WriteLine (adder (10 ));
}
// Printout: 15 15 15 15
Obviously, this is a serious error! Each returned function is added to 5. This is because the loop variable is overwritten, and the final value of the loop variable is 5.
To make it run in C #3 and 4, you have to remember to copy the loop variable in the loop range to the local variable first, and then overwrite the local variable with Lambda.
Foreach (var addend _ in addends ){
Var addend = addend _;
// DON't GO NEAR THE LOOP VARIABLE
Funcs. Add (I => I + addend)
}
Because the function overwrites the local variable rather than the cyclic variable, you can save this value and get the correct result.
By the way, this is not a vague example-I have encountered it many times in the project. In fact, I have encountered implementing a filter function in a project. This function is composed of user-specific restricted object sets. The Code processes the constraint object cyclically and constructs a list of functions that represent the clause (for example, Name Equals "BOB" is changed to r => r ["Name"] = "BOB "), then combine these functions into the final filter and run all the clauses to check whether they are true. I did not run successfully for the first time, because all the clauses cover the last one in the same constraint object-set.
C #5 fixes this issue and you will be able to get the expected results. If you want to use the hybrid Object-Oriented function feature of C #, it avoids a big trap that has been creating problems for years.
From a Language Perspective, C #5 does not have many new features to be learned, although asynchronous programming and waiting keywords are indeed two major breakthroughs. Happy programming!
Author Wang ran