This post focuses on a simple review of the C # language knowledge points that need to be grasped by ASP. C # 3.0, especially the C # language features. For kids who are learning ASP. NET MVC, take a few minutes to browse. The C # knowledge points to be reviewed in this article are: attributes, automatic attributes, object collection initializers, extension methods, lambda expressions, and LINQ queries. C # veteran "player" can pass by.
1. Features (Attributes)
Feature (Attributes), MSDN is defined as: The common language runtime allows you to add a descriptive declaration like a keyword, called Attributes, that labels elements in your program, such as types, fields, methods, and properties. Attributes and Microsoft. NET Framework file metadata are saved together to describe your code to the runtime, or to affect the behavior of your application as it runs.
For example, when you label a [Obsolete] attribute before a method, when you call the method, Vs prompts for a warning that the method has expired, such as:
Also, in a remote object of. Net remoting, if you want to invoke or pass an object, such as a class, or struct, the class or struct must label the [Serializable] attribute. Also, one of the many things we use when building XML Web Services is [Webmegthod], which allows you to encode the return value of the public method of an HTTP request into XML for delivery.
The attribute is actually a class, the actual class name of the [Obsolete] attribute is ObsoleteAttribute, but we can label it without the attribute suffix, and the system automatically adds it to us when the name is converted.
That's what they say. NET system defines some of the features, of course there are many. Knowing how to customize features, it is advantageous for us to use features in ASP. NET MVC programming, such as to validate the legitimacy of form input with attribute labeling attributes of the model class (described later).
Let's simulate the Stringlenth feature that ASP. NET MVC often uses to determine whether user input exceeds the length limit. Let's simulate it now. First define a mystringlenth feature:
A user-defined Mystringlenthattribute attribute class with optional named arguments. This attribute is restricted by AttributeUsage it can only be used on properties and fields. [AttributeUsage (Attributetargets.property | Attributetargets.field)]public sealed class Mystringlenthattribute:attribute {public Mystringlenthattribute ( string displayName, int maxLength) {this . MaxLength = MaxLength; This. DisplayName = DisplayName; } The displayed name, which is read-only, cannot be assigned by an optional parameter and must be initialized in the constructor. Public string DisplayName {get; private set;} The maximum length value, which is read-only, cannot be assigned by an optional parameter and must be initialized in the constructor. public int MaxLength {get; private set;} Error message, which can be used as an optional named parameter when labeling. Public string ErrorMessage {get; set;} The minimum length value, which can be used as an optional named parameter when labeling. public int MinLength {get; set;}}
Without AttributeUsage restrictions, attributes can be declared before types (such as structs, classes, enumerations, delegates) and members (such as methods, fields, events, properties, indexes).
We then apply this feature to the following order class:
Apply the custom Mystringlenth attribute above the OrderID property of the Order class. MinLength and errormessage are named parameters. public class Order { [Mystringlenth ("Order number", 6,minlength = 3, errormessage = "{0} length must be between {1} and {2}}, please re-enter!") ")] public string OrderID {get; Set }}
Finally we look at how to use the Mystringlenth feature to verify the length of the user input string:
Checks if the length of the member string is more limited. private static bool Ismembervalid (int inputlength, MemberInfo member) {foreach (object attribute in member. GetCustomAttributes (True)) {if (attribute is Mystringlenthattribute) {Mystringlenthattribute attr= (MyS Tringlenthattribute) attribute; String displayName = attr. DisplayName; int maxLength = attr. MaxLength; int minLength = attr. MinLength; String msg = attr. errormessage; if (Inputlength < MinLength | | inputlength > MaxLength) {Console.WriteLine (msg, DisplayName, Minleng th, maxLength); return false; } else {return true; }}} return false;} Verify that the input is legal private static bool IsValid (order order) {if (order = = null) return false; foreach (PropertyInfo p in typeof (Order). GetProperties ()) {if (Ismembervalid) (order. Orderid.length, p)) return true; } return false;} Public statIC void Main () {string input=string. Empty; Order order; Do {Console.WriteLine ("Please Enter order number:"); input = Console.ReadLine (); Order = New Order {OrderID = input}; } while (! IsValid (order)); Console.WriteLine ("Order number entered correctly, press any key to exit!") "); Console.readkey ();}
The output effect is as follows:
2. Automatic attributes
In C # 3.0 and later versions, auto-implemented properties make property declarations more concise when no additional logic is required in the accessors of the property.
The following example shows the standard implementation and automatic implementation of a property:
Class Program { class Person { //Standard implemented attribute int _age; public int Age { get {return _age;} set { if (value < 0 | | value >) { Console.WriteLine ("The Age of the settings is incorrect! "); return; } _age = value; } } Auto-implemented property public string Name {get; set;} } static void Main (string[] args) {person p = new Person (); P.age = n; P.name = "Xiao Wang"; Console.WriteLine ("{0} this year {1} years old. ", p.name,p.age); Console.readkey (); }}
Automatic attributes can also have different access rights, such as:
public string Name {get;private set;}
Note that automatic properties cannot define read-only or write-only properties, and both get and set accessors must be provided:
public string Name {get;} Compilation error public string PetName {set;} Compilation error
3. Initializers for objects and collections
Above we demonstrate the automatic properties when initializing an instance of an object is an attribute to be assigned, and how many attributes will be required for how many lines of code. There is an object collection initializer in C # 3.0 and later, and with it, you can initialize all the properties of an object or collection of objects with just one line of code. This first creates a "commodity" class for the following example demo:
<summary>///Commodity///</summary>public class Product {//<summary>///Product Code/// </ summary> public int ProductID {get; set;} <summary>///Product Name/// </summary> Public string name {get; set;} <summary>///Product Description/// </summary> public string Description {get; set;} <summary>///commodity prices/// </summary> Public decimal price {get; set;} <summary>///goods category/// </summary> Public string category {set; get;}}
Based on the commodity class defined above, the following code demonstrates how to create an instance object and a collection of commodity classes through an initializer:
The use of the static void Main (string[] args) { //object initializer (which can only be assigned to a partial field) Product Product = new Product {ProductID = 1234, Name = "Watermelon", Price = 2.3M};//Create and initialize an instance //collection initializer using list<product> prolist = new List<product> { new Pr oduct {ProductID = 1234, name = "Watermelon", Price = 2.3M}, new Product {ProductID = 2345, name = "Apple", Price = 5.9M } , new Product {ProductID = 3456, Name = "cherry", Price = 4.6M} }; Print Console.WriteLine ("Object initializer: {0} {1} {2}", product. ProductID, product. Name, product. Price); foreach (Product p in prolist) { Console.WriteLine ("collection initializer: {0} {1} {2}", P.productid, P.name, P.price); } Console.readkey ();}
There are also other types of initializers that can be used, as follows:
Array using initializer string[] Fruitarray = {"Apple", "orange", "Plum"};//anonymous type using initializer var books = new {Title = "ASP.", Author = "Xiao Wang", price = 20};//dictionary type using initializer dictionary<string, int> fruitdic = new dictionary<string, int> () { "app Le ", ten}, {" Orange ", +}, {" Plum ", 30}};
4. Extension methods
The extension method enables you to "add" methods to an existing type without creating a new derived type or modifying the original type. An extension method is a special static method, but it can be called just like an instance method on an extended type. For example, we can have all instance objects of the random class have a method that returns a random bool value. We cannot modify the random class itself, but we can extend it, as shown in the following code:
Static class Program { ///<summary>/////// <param name= The "random" >this parameter is automatically assigned to an instance of random </param>/// <returns></returns> public static bool Nextbool (this random random) { return random. Nextdouble () > 0.5; } static void Main (string[] args) { //Call extension method Random rd = new random (); bool bl = Rd. Nextbool (); Console.WriteLine (BL. ToString ()); Console.readkey (); }}
Note that the extension method must be defined in a non-generic static class, and the program class above will have an error if the static modifier is not added.
We can create an extension method of an interface so that the class that implements the interface can call the extension method. Take a look at the following complete example:
<summary>///Shopping Cart Class (implements ienumerable<product> Interface)///</summary>public class ShoppingCart: ienumerable<product> {public list<product> products {get; set;} Public ienumerator<product> GetEnumerator () {return products.getenumerator (); } IEnumerator Ienumerable.getenumerator () {return GetEnumerator (); }}///<summary>///defines a static class for implementing an extension method (Note: The extension method must be defined in a static Class)///</summary>public static class Myextensionmethods {//<summary>////</summary> public static decimal totalprices (th is ienumerable<product> productenum) {decimal total = 0; foreach (Product prod in productenum) {total + = Prod. Price; } return total; }}class program {static void Main (string[] args) {//Create and initialize ShoppingCart instance, inject ienumerable<product> ienumerable<product> products = new ShoppingCart {products = new list<product>{New Product {name = ' Kayak ', price = 275}, new product {name = ' lifejacket ', Price = 48. 95M}, new product {name = ' soccer Ball ', price = 19.50M}, new product {name = "Corner flag ", Price = 34.95M}}; Create and initialize a normal Product array product[] Productarray = {New Product {Name = "Kayak", Price = 275M}, New Product {name = ' lifejacket ', Price = 48.95M}, new product {name = ' soccer Ball ', price = 19.50M}, New Product {Name = "Corner flag", Price = 34.95M}}; Get Total Price: Call the Totalprices extension method in the same way as the interface. Decimal carttotal = products. Totalprices (); Get Total Price: Call the Totalprices extension method in normal array mode. Decimal arraytotal = Productarray.totalprices (); Console.WriteLine ("Cart total: {0:c}", carttotal); Console.WriteLine ("Array total: {0:c}", arraytotal); Console.readkey (); }}
The following results are output after execution:
5.Lambda-expression
LAMBDA expressions and anonymous functions are actually one thing. The difference is that their grammatical representations are different, and the LAMBDA expression is actually a shorthand for the anonymous function in syntax. A direct introduction to the use of anonymous functions and lambda expressions is not very interesting, here, I would like to use the actual application of a two-way example, so that in the introduction of knowledge points can also share with you the idea of solving the problem.
If we want to implement a powerful product query method, this commodity query method how to query the product can be determined by the user himself, the user can be based on the price to inquire about the goods, but also according to the classification to query the goods and so on, that is, users can pass their own query logic to this query method. To write such a method, it is natural to think of a delegate as the parameter of this method, which is the logic that the user handles the commodity query. We call this query method "Commodity finder". We can implement this "commodity finder" with static extension methods, so that each commodity collection object (such as ienumerable<product> products) can call the static method directly to return the query result. The idea of solving the problem is there, and then it is realized. Perhaps you are a bit of a description of this paragraph, and the combination of code may make you clearer. Here is the implementation code for this "commodity Finder"-filter method:
<summary>///defines a static class for implementing extension methods//</summary>public static class Myextensionmethods {// < summary>///Product Finder///</summary>// <param name= "productenum" > Extension Type instance reference </param> /// <param name= "Selectorparam" > a parameter type of product, a delegate with a bool value of $ </param>// <returns> Query Results </returns> public static ienumerable<product> Filter (this ienumerable<product> productenum, Func<product, bool> selectorparam) { foreach (Product prod in productenum) { if (Selectorparam (prod)) {
yield return prod;}}}
Yes, we are using such a short filter method to meet the various needs of the query. The product class above is defined by the previous article. Once again, the effectiveness of the extension method is witnessed. To demonstrate the invocation of the filter query method, we first create a batch of data:
static void Main (string[] args) { //Create commodity collection ienumerable<product> products = new ShoppingCart { Products = new List<product> { new product {name = "Watermelon", Category = "fruit", Price = 2.3M}, new Product {name = "Apple", category = "fruit", Price = 4.9M}, new Product {Name = "Introduction to ASP.", Category = "book", Price = 19.5M}, new Product {Name = "net MCV improved", Category = "book", Price = 34.9M} } ;}
Next we continue to invoke the Query method in the main method above filter:
Use the anonymous function to define a specific query requirement func<product, bool> fruitfilter = Delegate (Product prod) { return prod. Category = = "fruit";};/ /Call filter, query the product classified as "fruit" ienumerable<product> filteredproducts = products. Filter (fruitfilter);//print result foreach (product prod in filteredproducts) { Console.WriteLine ("Product name: {0}, Unit Price: {1:C}", Prod. Name, prod. Price);} Console.readkey ();
The output is:
Above, we use a delegate and an anonymous function to handle the user query logic and pass it to the filter method to meet the requirements described above. But using a lambda expression instead of the anonymous function above can make the above code look more concise and user-friendly, as shown in the following code:
Func<product, bool> fruitfilter = prod = prod. Category = = "Fruit";ienumerable<product> filteredproducts = products. Filter (Fruitfilter);
Without the delegate keyword, it looks more comfortable without the size brackets. Of course, the above two lines of code can continue to be simplified to one line:
Ienumerable<product> filteredproducts = products. Filter (prod = prod. Category = = "fruit");
The output of these three methods is the same. Then, we can also implement queries for a variety of requirements through lambda expressions:
Inquiries classified as "fruit" or the unit price is greater than 30 yuan ienumerable<product> filteredproducts = products. Filter (prod = prod. Category = = "Fruit" | | Prod. Price > 30);
With this example, I believe you have a clear understanding and hold of the simple application of lambda expressions, which is enough:).
6.LINQ
Finally, a brief review of LINQ. LINQ (Language Integrated Query Language integrated queries) is a breakthrough innovation in VS 2008 and. NET Framework version 3.5, which bridges the object and data realms.
The way a lambda expression is used to query the result set is a bit of a hassle (because you have customized a filter extension method), and LINQ itself is a collection of many extension methods, which we can use directly, greatly simplifying the work of writing query code. For example, for such a data collection:
Product[] Products = { new product {name = "Watermelon", Category = "fruit", Price = 2.3M}, new product {name = "Apple", Categor y = "fruit", Price = 4.9M}, new product {name = "water Spinach", Category = "vegetable", Price = 2.2M}, new product {Name = "sweet potato", Cate Gory = "vegetable", Price = 1.9M};
If you are querying for the top three commodity information, if you do not use LINQ, we may first write a sorting method that sorts products according to their price from high to low, and a new product[] object is used to store sorted data. But with LINQ you can do much less work, and one or two code will do it. Find the top three items as shown in the code below:
var results = From product in the products by product. Price Descending Select new { product. Name, product. Price};//prints the highest priced three items int count = 0;foreach (var p in results) { Console.WriteLine ("Product: {0}, Price: {1}", P.name, p. Price); if (++count = = 3) break;} Console.readkey ();
Output Result:
It's cool to be familiar with LINQ. The above LINQ statements are similar to our familiar SQL query statements and look neat and understandable. But not every SQL query statement has a corresponding keyword in C #, and sometimes we need to use another LINQ query, the "dot" approach to LINQ queries, in which LINQ query methods are extension methods. The following code is the same as the above implementation:
var results = Products . OrderByDescending (e = e.price) . Take (3) . Select (E = new {E.name,e.price}), foreach (Var p in results) { Console.WriteLine ("Product: {0}, Price: {1}", P.name, P.price );} Console.readkey ();
Although the LINQ query for class SQL looks more straightforward than this, not every SQL query statement has a corresponding keyword in C #, such as the take extension method, which is not a function of the LINQ query syntax of Class SQL.
Note that some LINQ extension methods are categorized as "deferred query" (deferred) and "Instant query" (immediate). Deferred query means that LINQ statements that have a "deferred query" extension method only begin to actually execute the query when the result set object is called, and instant queries get results immediately. For example, the OrderByDescending extension method of the above LINQ statement is a "deferred query" method, when the program executes into the LINQ Statement Definition section and does not query the results and put into the results object, Instead, the LINQ query statement is actually executed when the program executes into the Foreach loop to get the results of the query. We can do a test, after the Ling statement, we re-assign the Products[1] object, as shown in the following code:
var results = Products . OrderByDescending (e = e.price) . Take (3) . Select (E = new {e.name, e.price}),//re-assign to products[1 after LINQ statement products[1] = new Product {Name = "Durian", Category = "fruit ", Price = 22.6M};//print foreach (var p in results) { Console.WriteLine (" Product: {0}, Cost: {1} ", P.name, P.price);} Console.readkey ();
The output is:
We find that results is the result of a re-assignment. It is conceivable that the query statement was actually executed after the results was called.
LINQ is very powerful and easy to use, just as a simple review of what you need to know before learning ASP. You need to use LINQ more often than not to be flexible and skilled.
C # Knowledge Point feed