Static extension methods for generic collections

Source: Internet
Author: User
Tags sorts

Generic collections in C # provide a number of static extension methods based on Enumerable, such as Find, Average, Distinct, etc., in useBasic DatatypeCollection, you can call these methods directly, but if you are a custom type, you should do so based on the interface required by the extension method.Custom-type extension interfacesClass, the essence of which is to use an instance method of an extension class to complete a particular operational logic, otherwise the operation of the collection will be invalid. In this paper, an example is described.

The

First requires a custom class, which is a simple class that represents the attributes of a natural person, lists the name, age, and gender

    public class Person    {         public person (String name, int age, sex sex)          {            name  = name;            Age = age;             Sex = sex;         }        public string name  { get; set; }        public int age  { get; set; }        public sex sex  { get; set; }        public override  String tostring ()         {             return string. Format (String. Format ("Name : {0} \t age :{1} \t sex :{2}",  name, age,  sex.sexstring ()));         }    }

The next step is to create a collection and add some random collection elements.

list<person> list = new list<person> (); list. ADD (New Person ("MISS DD", Sex.female)), list.  ADD (New Person ("MR. DD ", Sex.male)); list. ADD (New Person ("MRS DD", Sex.unknow));//To save the sort result list<person> result = new list<person> ();

First try the basic data types and sort by age:

Just a list. The p.sex (p = =) does not require any extra code to complete. How is it implemented?

Of course, look at the document definition first, the static extension method is defined in the public static class Enumerable class:

////  Summary: //      Sorts the elements of a sequence in ascending order according to the key.   parameter: //   source://      a sequence of values to sort.    keySelector://      functions for extracting keys from an element. The type of the element in the   type parameter: //   tsource://     source .    TKey://     keySelector  the type of the key returned.   Returns the result: //      a  system.linq.iorderedenumerable<telement> Its elements are sorted by key.   Exception:  //   system.argumentnullexception://     source   or  keySelector  for  null. Public static iorderedenumerable<tsource> orderby<tsource, tkey> (this  Ienumerable<tsource> source, func<tsource, tkey> keyselector); 

Definition at a glance, two parameters are listed in this method list. The first one uses this prefix to illustrate the type of this method extension, the second parameter is a function delegate, which is equivalent to a function pointer in C + +, which means that the code is going to bring in a function here. where TSource and TKey represent the type requirements of the function.

In list. (p = = p.sex); The expression type parameter is not seen because the list collection already implements the IEnumerable interface, you can omit this parameter, and the anonymous expressions can infer the type themselves.

Of course, you can also use the strongly typed syntax to write this:

List. Orderby<person, Int> (delegate (person p) {return p.age;});

It is easier to see the intent of TSource and TKey using this type of notation. The type of the parameter entered in the anonymous delegate is TSource (person), and the type of the return value is TKey (int). To say that plain English is tsource is person, need to sort the list element type,TKey is int, our type of age property, that is, we choose the keyword as the sorting standard.

That if we want to achieve their own sort, such as now is to go in line, need the principle of the first lady, then we can directly change the TKey to sex not on the line?

List. Orderby<person, Sex> (delegate (person p) {return p.sex;});

Try it:

The order of discovery has changed since the execution, but the principle of first lady has not been fulfilled. But what sort of execution is it now?

Enumerating types in C # is strictly not considered an underlying data type, but its implementation is implemented on the basis of integer values and can be defined as an enum Enumclass:short (or Int/long) as an integer value type, continuing to observe the sort result as if it were is consistent with the order of enumeration members.

You can guess that at this point. The ordering of the enumeration collection may be based on the integer value corresponding to the enumeration member. Now you can verify that the default value of the enumeration element is modified

public enum sex:ushort{unknow =3, Male = 1, Female = 2,}

Executed again, the results are as follows:

You can see that the order of arrangement has been refreshed, the Male with the smallest value is ranked first, and the unknow with the highest value is the last. Then the enumeration collection defaults to the validation by the guess of the member-defined value-size sort .

Go back to our question: to achieve the principle of the first lady, then according to the above conclusion only need to set the value of Famle to a minimum can be done. This should be the simplest and clearest way.

But the reality is often cruel, how simple the light is not necessarily reliable ah! For example, what if a person's information data is read from a database, and the definition of gender has been fixed in the database and cannot be modified? Or are our types not simple enumerations, but more complex classes?

Method. Net has been provided for us,   in the MSDN documentation; ORDER BY There is another definition that allows us to implement custom sorting for any purpose--- --(thankfully, I've learned a bit about C + + templates, and the definition here is quite gracious)

  Summary: //      Sorts the elements of a sequence in descending order using the specified comparer.   parameter: //   source://      a sequence of values to sort.    keySelector://      functions for extracting keys from an element.    comparer://      a   for comparing keys System.collections.generic.icomparer<t>. The type of the element in the   type parameter: //   tsource://     source .    TKey://     keySelector  the type of the key returned.   Returns the result: //      a  system.linq.iorderedenumerable<telement> The elements are sorted in descending order according to a key.   Exception:  //   system.argumentnullexception://     source   or  keySelector  for  null. Public static iorderedenumerable<tsource> orderbydescending<tsource, tkey> ( This ienumerable<tsource> source, func<tsource,&nBsp Tkey> keyselector, icomparer<tkey> comparer);

In this definition, a parameter of an interface type is required, and the interface class needs to implement the IComparer comparer. From the description of the TKey type, you can see that this interface is required for the Sex attribute.

Well, let's do it. It is necessary to create an interface class that inherits IComparer<Sex>, which is also very simple for the IComparer interface, and its return value represents the size flag of the first parameter relative to the second parameter. If small returns a value less than 0, large returns a value greater than 0, and equal returns 0. Almost all collection operations are inseparable from it, so for our scenario, it is necessary to add a female priority to the comparison (that is, to let girls return values less than 0).

<SUMMARY>///implements the interface class of the comparator///</summary>public class Isexcomparer:icomparer<sex>{public int Compare (Sex x, sex y) {if (x = = Sex.female) Return-1;else if (y = = Sex.female) return 1;return (int) x-(int) y;}}

Now that the interface class has, how do we call it?

In fact, the parameters of the function signature is easy to understand, but how to write code when it is not necessarily on, not afraid of everyone jokes, I first use this style of the method when a glance to see the need for this a comparator class, suddenly feel very proud of themselves is simply too smart, then, and then bring into the parameters, And then it's naïve to say that.

result = list. (p = p.sex, isexcomparer);

is to put this type written in, and then a look at the wrong ah, how to error, replaced typeof (Isexcomparer), I went to also reported wrong, hopeless. At that time Leng silly do not know how to write, alive suppressed for a while to serve the soft to ask the degree Niang ... Now think about the death of laughter, for Mao not serious look at the parameters of the requirements? Not some type, it's a variable Ah! Variable Ah!

Create the comparator isexcomparer Sexcomparer = new Isexcomparer ();//Bring the comparator as a parameter into the list. Orderby<person, Sex> (delegate (person p) {return p.sex;}, Sexcomparer);

Complete, of course, the diagram can be combined into one line of code:

List. (p = p.sex, New Isexcomparer ());

Review the results again:

It's done, just like the expected output.

Finally, the collection of C # provides a lot of easy-to-use generics, all based on the static extension method, which is essentially a template method in C + + that,fuc<tsource,tkey> the concept of a corresponding function pointer, telling the program to invoke the specified method when executing. because A function pointer cannot be passed directly in C #, so the first contract used by interface, the user can then implement a strongly typed interface class, pass the function through an instance variable, and finally complete the element move or pick operation by passing in the function.

The last one is two small references:

If you find that the program is dead or unresponsive when you use the IComparer interface, check that the Compare method is not a logical error. If our top Compare is written down like this,

public int Compare (sex x, sex y) {if (x = = Sex.female) Return-1;else if (x = = Sex.male) return 1;return (int) x-(int) y;}

Will cause the program to fall into a dead loop. Look, it's Female. Return -1,male return 1, right? However, this filter will leave the parameter y, it should be remembered that the compare need to judge the two values before and after the comparison, for the same condition X, y must make a judgment, throw away one, will cause the element in this position has not been manipulated, and can not complete the task.

You can use the static extension method to override the functionality of the completion interface or the base class method that is not easily overridden in inheritance. For example, the sex attribute in the person class is an enumeration type, and there is no ToString method, which is done using the extension method for easy output.

<SUMMARY>///provides a convenient way to obtain a static extension of the string representation///</summary>public Static class Sexext{public static string Sexstring ( This sex Sex) {if (sex = = Sex.female) return "female", if (sex = = Sex.male) return "male"; return "Unknown";}}


Static extension methods for generic collections

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.