[ASP.]02-c# Knowledge Point Summary

Source: Internet
Author: User
[ASP.NET
MVC Mavericks Road] 02-C # Knowledge Point

This blog post is a brief review of the C # language knowledge that asp.net mvc development needs to support, especially some C # language features only available in C # 3.0. For children who are learning asp.net mvc, take a few minutes to browse. The C # knowledge points to be reviewed in this article are: features, automatic properties, object collection initializers, extension methods, Lambda expressions, and Linq queries. C # senior "players" can pass by.

Article Directory

1.Attributes

Attributes, the definition of MSDN is: the common language runtime allows you to add keyword-like descriptions, called attributes, which mark elements in the program, such as types, fields, methods, and attributes. Attributes are stored with the metadata of the Microsoft .NET Framework file and can be used to describe your code to the runtime or to influence the behavior of the application while the program is running.

For example, if you mark the [Obsolete] attribute before a method, VS will prompt a warning that the method has expired when the method is called, such as:

For another example, in the remote object of .Net Remoting, if you want to call or pass an object, such as a class or a structure, the class or structure must be marked with the [Serializable] attribute. Also, one of the features we use a lot when building XML Web services is [WebMegthod], which allows the return value of public methods via HTTP requests to be encoded as XML and passed.

The attribute is actually a class. The actual class name of the [Obsolete] attribute is ObsoleteAttribute, but we can add the attribute without the suffix when labeling.

All of the above are some of the features defined by the .NET system, and of course there are many more. Understanding how to customize the features will help us better use the features in ASP.NET MVC programming, such as labeling the attributes of the Model class to verify the validity of form input (introduced later).

Let's simulate a StringLenth feature that is often used by ASP.NET MVC. It is used to determine whether the user input exceeds the length limit. Let's simulate it now. First define a MyStringLenth attribute:

// User-defined MyStringLenthAttribute attribute class with optional named parameters.
// This feature is restricted to attributes and fields via AttributeUsage.
[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 is externally read-only, so it cannot be assigned by optional parameters, it must be initialized in the constructor.
    public string DisplayName {get; private set;}

    // The maximum length is externally read-only, so it cannot be assigned by optional parameters, it must be initialized in the constructor.
    public int MaxLength {get; private set;}

    // Error information, can be used as an optional named parameter when labeling.
    public string ErrorMessage {get; set;}

    // Minimum length, can be used as an optional named parameter when labeling.
    public int MinLength {get; set;}
}
Without the AttributeUsage restriction above, attributes can be declared before types (such as structures, classes, enums, delegates) and members (such as methods, fields, events, attributes, indexes).

Then we apply this feature to the following Order class:

// Apply a custom MyStringLenth attribute to the OrderID property of the Order class. MinLength and ErrorMessage are named parameters.
public class Order {
    [MyStringLenth ("Order number", 6, MinLength = 3, ErrorMessage = "The length of {0} must be between {1} and {2}, please enter it again!")]
    public string OrderID {get; set;}
}
Finally we look at how to verify the length of a user input string using the MyStringLenth feature:

// Check if the member string length exceeds the limit.
private static bool IsMemberValid (int inputLength, MemberInfo member) {
    foreach (object attribute in member.GetCustomAttributes (true)) {
        if (attribute is MyStringLenthAttribute) {
            MyStringLenthAttribute attr = (MyStringLenthAttribute) 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, minLength, maxLength);
                return false;
            }
            else {
                return true;
            }
        }
    }
    return false;
}

// Verify whether 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 the order number:");
        input = Console.ReadLine ();
        order = new Order {OrderID = input};
    }
    while (! IsValid (order));
    Console.WriteLine ("Order number is entered correctly, press any key to exit!");
    Console.ReadKey ();
}
The output is as follows:

2. Automatic attributes

In C # 3.0 and later, automatically implemented attributes can make attribute declarations more concise when no additional logic is needed in the accessor of the attribute.

The following examples demonstrate the standard and automatic implementation of attributes:

class Program {
    class Person {
        // standard implementation properties
        int _age;
        public int Age {
            get {return _age;}
            set {
                if (value <0 || value> 130) {
                    Console.WriteLine ("The age is set incorrectly!");
                    return;
                }
                _age = value;
            }
        }

        // Automatically implemented attributes
        public string Name {get; set;}
    }
        
    static void Main (string [] args) {
        Person p = new Person ();
        p.Age = 180;
        p.Name = "Little King";
        Console.WriteLine ("{0} {1} years old this year.", 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. You must provide both get and set accessors:

public string Name {get;} // Compile error
public string PetName {set;} // Compile error

3. Object and collection initializers

Above, we demonstrated that when an automatic instance is initialized, an attribute is assigned to each instance of the object. As many attributes as necessary require as many lines of code. C # 3.0 and later have an object collection initializer, with which you can initialize all the properties of an object or an object collection with a single line of code. This first creates a "commodity" class for later example demonstration:

/// <summary>
/// product category
/// </ summary>
public class Product {
    /// <summary>
    /// Product Number
    /// </ 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>
    /// product price
    /// </ summary>
    public decimal Price {get; set;}
    /// <summary>
    /// Categories
    /// </ summary>
    public string Category {set; get;}
}
Based on the commodity class defined above, the following code demonstrates how to create instance objects and collections of the commodity class through the initializer:

static void Main (string [] args) {
    // The use of the object initializer (only assign values to some fields)
    Product product = new Product {ProductID = 1234, Name = "Watermelon", Price = 2.3M}; // Create and Initialize an instance

    // Use of collection initializer
    List <Product> proList = new List <Product> {
        new Product {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 other types that can also use initializers, as follows:

/ Array using initializer
string [] fruitArray = {"apple", "orange", "plum"};
// Anonymous type uses initializer
var books = new {Title = "Getting started with ASP.NET MVC", Author = "Little King", Price = 20};
// Dictionary type uses initializer
Dictionary <string, int> fruitDic = new Dictionary <string, int> () {
    {"apple", 10},
    {"orange", 20},
    {"plum", 30}
};
4. Extension method

Extension methods enable you to "add" methods to existing types without creating new derived types or modifying the original types. Extension methods are special static methods, but can be called like instance methods on extension types. For example, we can have all instances 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>
    /// Randomly return true or false
    /// </ summary>
    /// <param name = "random"> this parameter is automatically assigned to the Random instance </ 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. The above Program class will report an error if the static modifier is not added.

We can create an extension method for an interface so that classes that implement the interface can call the extension method. Look at a complete example below:

/// <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>
/// Define a static class for implementing extension methods (note: extension methods must be defined in a static class)
/// </ summary>
public static class MyExtensionMethods {
    /// <summary>
    /// Calculate the total price of the product
    /// </ summary>
    public static decimal TotalPrices (this 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 a ShoppingCart instance and 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 the total price of the product: Call the TotalPrices extension method with an interface.
        decimal cartTotal = products.TotalPrices ();
        // Get the total price of the product: Call the TotalPrices extension method in the form of an ordinary array.
        decimal arrayTotal = productArray.TotalPrices ();

        Console.WriteLine ("Cart Total: {0: c}", cartTotal);
        Console.WriteLine ("Array Total: {0: c}", arrayTotal);
        Console.ReadKey ();
    }
}
The output after execution is as follows:

5.Lambda expression

Lambda expressions and anonymous functions are actually one thing. The difference is that they have different syntax expressions. Lambda expressions are syntactically shorthand for anonymous functions. It is not interesting to directly introduce the usage of anonymous functions and Lambda expressions. Here, I will give an example of the usage of both based on practical applications. In this way, I will share the ideas of solving problems while introducing knowledge points.

If we want to implement a powerful product query method, how the product query method can query the product can be determined by the user himself, the user can query the product based on the price, can also query the product based on the classification, etc. You can pass your own query logic to this query method. To write such a method, we will naturally think of using a delegate as the parameter of this method. This delegate is the logic for the user to process the product query. We can't help but call this query method the "commodity finder." We can use static extension methods to implement this "commodity query", so that each product collection object (such as IEnumerable <Product> products) can directly call the static method to return the query results. With the idea of solving the problem, the next step is to achieve it. Maybe you have a bit of a description of this paragraph, combined with the code may make you clearer. The following is the implementation code of the "Commodity Query" -Filter method:

/// <summary>
/// Define 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 delegate with parameter type Product and return value bool </ 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;
            }
        }
    }
}
That's right, we just use such a short Filter method to meet various needs of the query. The Product class used above is defined above. Here again, we witness the power of the extension method. To demonstrate the call of the Filter query method, let's first create a batch of data:

static void Main (string [] args) {
    // create product 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 = "Getting Started with ASP.NET MCV", Category = "Books", Price = 19.5M},
            new Product {Name = "ASP.NET MCV Boost", Category = "Books", Price = 34.9M}
        }
    };
}
Next, we continue to call the query method Filter in the Main method above:

// Define a specific query requirement with anonymous functions
Func <Product, bool> fruitFilter = delegate (Product prod) {
    return prod.Category == "fruit";
};

// Call Filter to query products classified as "fruit"
IEnumerable <Product> filteredProducts = products.Filter (fruitFilter);

// Print the 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 used the delegate and anonymous functions to handle the user query logic and passed it to the Filter method, which met the needs mentioned earlier. However, if you use a Lambda expression instead of the anonymous function above, the above code will look more concise and humane, as shown in the following code:

Func <Product, bool> fruitFilter = prod => prod.Category == "fruit";
IEnumerable <Product> filteredProducts = products.Filter (fruitFilter);
Without the delegate keyword and without the parentheses, it looks more comfortable. Of course, the above two lines of code can be reduced to one line:

IEnumerable <Product> filteredProducts = products.Filter (prod => prod.Category == "fruit");
The output of all three methods is the same. Then, we can also implement queries with various requirements through Lambda expressions:

// Query products classified as "fruit" or unit price greater than 30 yuan
IEnumerable <Product> filteredProducts = products.Filter (prod =>
    prod.Category == "fruit" || prod.Price> 30
);
Through this example, I believe that everyone has clearly understood and supported the simple application of Lambda expressions, and this is enough :).


6.LINQ

Finally, a brief review of LINQ. LINQ (Language Integrated Query Language Integrated Query) is a breakthrough innovation in VS 2008 and .NET Framework version 3.5, which builds a bridge between the object domain and the data domain.

When talking about Lambda expressions above, the way of querying the result set is still a bit cumbersome (because a Filter extension method is customized), and Linq itself has a lot of extension methods that we can use directly, which greatly simplifies writing The query code works. For example, for such a data set:

Product [] products = {
    new Product {Name = "Watermelon", Category = "Fruit", Price = 2.3M},
    new Product {Name = "Apple", Category = "Fruit", Price = 4.9M},
    new Product {Name = "Hot Vegetables", Category = "Vegetables", Price = 2.2M},
    new Product {Name = "Sweet Potato", Category = "Vegetables", Price = 1.9M}
};
If you want to query the three most expensive product information, if you do n’t use Linq, we may first write a sort method to sort products according to price from high to low. When sorting, you need to create a new Product [] object for Store sorted data. But using Linq can greatly reduce the workload, one or two sentences can be done. As shown in the following code, find the three most expensive products:

var results = from product in products
                orderby product.Price descending
                select new {
                    product.Name,
                    product.Price
                };
// Print the three most expensive products
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 results:

Being proficient with Linq is a great thing. The above Linq statement is similar to the familiar SQL query statement, and it looks very neat and easy to understand. But not every SQL query has a corresponding keyword in C #. Sometimes we need to use another Linq query method, that is, the "dot" method of the Linq query method. The Linq query methods in this method are Is the extension method. For example, the following code has the same effect as above:

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 SQL-like Linq query method looks more clear than this method, not every SQL query statement has a corresponding keyword in C #. For example, the Take extension method here is a feature that the SQL-like Linq query syntax does not have. .

Note that some Linq extension methods are divided into "deferred" and "immediate". Deferred query means that the Linq statement with the "deferred query" extension method only starts to actually execute the query when the result set object is called, and the immediate query obtains the result immediately. For example, the OrderByDescending extension method of the above Linq statement is a "deferred query" method. When the program is executed to the definition part of the Linq statement, the results are not queried and placed in the results object, but only when the program executes the foreach loop. Run the Linq query to get the query results. We can do a test. After the Ling statement, we reassign 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 products [1] after the Linq statement
products [1] = new Product {Name = "Durian", Category = "Fruit", Price = 22.6M};

//print
foreach (var p in results) {
    Console.WriteLine ("Product: {0}, Price: {1}", p.Name, p.Price);
}
Console.ReadKey ();
The output is:

We found that results are the result of reassignment. It is conceivable that the query is actually executed after results is called.

Linq is very powerful and very easy to use. Here I just take it as a brief review of the knowledge points before learning ASP.NET MVC. To use Linq flexibly and proficiently, you need to use it frequently.


The above is the content of [ASP.NET MVC Mavericks Road] 02-C # Knowledge Point. For more related content, please pay attention to topic.alibabacloud.com (www.php.cn)!


Related Article

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.