How to parse C # extension Methods _c# Tutorial

Source: Internet
Author: User
Tags datetime exception handling inheritance instance method lowercase static class string format

In the process of project development using object-oriented language, more "inheritance" features are used, but not all scenarios are suitable for the use of "inheritance" features, and some of the basic principles of design patterns are also mentioned.

Inheritance related to the use of attributes: The inheritance relationship of an object is actually defined at compile time, so it is not possible to change the implementation inherited from the parent class at run time. The implementation of a subclass has a very close dependency on its parent, so that any change in the implementation of the parent class will inevitably result in a subclass change. When you need to reuse a subclass, if the inherited implementation is not appropriate to solve the new problem, the parent must override it or be replaced by a more appropriate class, which limits flexibility and ultimately limits reusability. Instead of inheriting features, more will be based on the composite/aggregate reuse principle, the "synthesis/aggregation Reuse principle": Try to use compositing/aggregation and try not to use class inheritance.

If the object in the new type should carry details about the additional behavior, it may sometimes be less appropriate to use the inherited attribute, for example, when dealing with a type, a sealed class, or an interface. In the face of these requirements, we sometimes write static classes that contain some static methods. However, excessive static methods can result in additional unnecessary overhead.

Overview of extension methods:

In the face of the above questions about "inheritance", and in the face of some of the requirements of the project, the way we need to solve these problems is to "extend the method." The introduction of "extension methods" in c#3.0 has the advantage of static methods and the readability of the code that invokes them. When you use an extension method, you can invoke the static method as you would call an instance method.

1. Basic principles of extension methods:

(1). C # only supports extension methods, extended attributes, extended events, extension operators, and so on.

(2). The extension method (the method preceded by the first argument) must be declared in a non-generic static class, the extension method must have a parameter, and only the first argument uses the this tag.

(3). When the C # compiler finds extension methods in static classes, it requires that the static classes themselves must have a file scope.

(4). C # compilation requires an "import" extension method. (Static methods can be arbitrarily named, the C # compiler takes time to find a method, needs to check all static classes in the file scope, and scans all of their static methods to find a match)

(5). Multiple static classes can define the same extension method.

(6). When extending a type with an extension method, the derived type is also extended.

2. Extension method declaration:

(1). Must be in a non nested, Non-generic static class (so it must be a static method)

(2). There is at least one parameter.

(3). The first parameter must be prefixed by attaching the This keyword.

(4). The first parameter cannot have any other modifiers (such as ref or out).

(5). The type of the first parameter cannot be a pointer type.

In the above two categories, a simple introduction to the basic features and declarative methods of the extension method, as well as the way in which the extension method is used, will be shown in the following code sample, and no longer be explained.

Two. Extension method principle Analysis:

The extension method is a unique method of C # that uses the attribute ExtensionAttribute in an extension method.

Once C # uses the This keyword to mark the first parameter of a static method, the compiler applies a custom attribute to the method internally, which is persisted in the metadata of the resulting file, which is stored in the System.core DLL assembly.

Any static class that contains at least one extension method also applies the attribute in its metadata, and any assembly contains at least one static class that conforms to the above characteristics, and its metadata applies that attribute as well. If the code uses a nonexistent instance method, the compiler will quickly scan all referenced assemblies, determine which ones contain extension methods, and then, in this assembly, scan the static class that contains the extension method.

If two classes in the same namespace contain methods with the same extension type, there is no way to use only the extension methods in one of the classes. To use a type with a simple name of a type (without a namespace prefix), you can import all of the namespaces in that type, but when you do so, you have no way to prevent the extension methods in that namespace from being imported.

Three. NET3.5 extension methods Enumerable and queryable:

In the framework, the maximum use of the extension method is for the LINQ service, and the framework provides a secondary extension method, located in the enumerable and Queryable classes under the System.Linq namespace. Enumerable most extensions are ienumerable<t>,queryable most extensions are iqueryable<t>.

Common methods in the 1.Enumerable class:

(1). Range (): One argument is the starting number and one is the number of results to be generated.

  public static ienumerable<int> Range (int start, int count) { 
   Long max = ((long) start) + count-1;
   if (Count < 0 | | | max > Int32.MaxValue) throw error.argumentoutofrange ("count"); 
   Return Rangeiterator (Start, count);
  }
  static ienumerable<int> rangeiterator (int start, int count) {for 
   (int i = 0; i < count; i++) yield return St Art + i;
  }

(2). Where (): A way to filter the collection, accept a predicate, and apply it to each element in the original collection.

 public static ienumerable<tsource> where<tsource> (this ienumerable<tsource> source, func< TSource, bool> predicate) {
   if (Source = null) throw Error.argumentnull ("source"); 
   if (predicate = = null) throw Error.argumentnull ("predicate"); 
   if (source is iterator<tsource>) return ((iterator<tsource>) source). Where (predicate);
   if (source is tsource[]) return to New Wherearrayiterator<tsource> ((tsource[)) source, predicate); 
   if (source is list<tsource>) return to New wherelistiterator<tsource> (list<tsource>) source, predicate );
   return new whereenumerableiterator<tsource> (source, predicate);
  }
  Public Whereenumerableiterator (ienumerable<tsource> source, Func<tsource, bool> predicate) { 
    This.source = source;
    This.predicate = predicate; 
   }

The above describes the range () and where () two methods, which also consist primarily of the Select (), by-by (), and so on.

Common methods in the 2.Queryable class:

(1). IQueryable Interface:

 <summary>///provides the ability to compute queries for a specific data source that does not specify a data type. </summary>///<filterpriority>2</filterpriority> Public interface Iqueryable:ienumerable {//
 /<summary>///Gets an expression tree associated with an instance of the <see cref= "T:System.Linq.IQueryable"/>. cref= t:system.linq.iqueryable "</summary>//////<returns>///associated with this instance of <see/>" <see "
 T:System.Linq.Expressions.Expression "/>.
 </returns> Expression Expression {get;}
 <summary>///Gets the type of the element that is returned when executing the expression tree associated with this instance of the <see cref= "T:System.Linq.IQueryable"/>.
 </summary>//////<returns>///a <see cref= "T:System.Type"/&GT; represents the type of the element returned when executing the expression tree associated with it.
 </returns> Type ElementType {get;}
 <summary>///Gets the query provider associated with this data source.
 </summary>//////<returns>///<see cref= t:system.linq.iqueryprovider "/>" associated with this data source.
 </returns> Iqueryprovider Provider {get;} }

(2). Where ():

 public static iqueryable<tsource> where<tsource> (this iqueryable<tsource> source, expression< Func<tsource, bool>> predicate) { 
   if (Source = null)
    throw error.argumentnull ("source"); 
   if (predicate = = null)
    throw error.argumentnull ("predicate");
   return source. Provider.createquery<tsource> (
    expression.call 
     ) (null, (
     MethodInfo) Methodbase.getcurrentmethod ()). MakeGenericMethod (typeof (TSource)), 
     new expression[] {source. Expression, Expression.quote (predicate)}) 
     );
  

(3). Select ():

  public static iqueryable<tresult> select<tsource,tresult> (this iqueryable<tsource> source, Expression<func<tsource, tresult>> selector) {
   if (Source = null)
    throw Error.argumentnull (" Source ");
   if (selector = = null) 
    throw error.argumentnull ("selector");
   return source. Provider.createquery<tresult> ( 
    expression.call 
     ) (null, (
     MethodInfo) Methodbase.getcurrentmethod ()). MakeGenericMethod (typeof (TSource), typeof (TResult)), 
     new expression[] {source. Expression, Expression.quote (selector)})
     );
  

The above is a simple parsing of the two classes in the extension method.

Four. Extension Method Example:

Because the extension method is actually a call to a static method, the CLR does not generate code to check for null values on the value of the expression that calls the method

1. Exception Handling code:

 <summary>///provides useful methods for parameter validation///</summary> public static class Argumentvalidator {///<summary&
  Gt If Argumenttovalidate is empty, a ArgumentNullException exception///</summary> public static void Throwifnull is thrown (object arg Umenttovalidate, String argumentname) {if (null = = ArgumentName) {throw new ArgumentNullException ("Argumentn
   Ame ");
   } if (null = = Argumenttovalidate) {throw new ArgumentNullException (ArgumentName); }///<summary>///If argumenttovalidate is empty, throw a ArgumentException exception///</summary> public static V OID Throwifnullorempty (String argumenttovalidate, String argumentname) {throwifnull (argumenttovalidate, ArgumentName
   ); if (argumenttovalidate = = string.
   Empty) {throw new ArgumentException (ArgumentName); }///<summary>///If condition is true, throw ArgumentException exception///</summary>///<param name= "Condit Ion "></param>///<param name=" MSG "&GT;&Lt;/param> public static void Throwiftrue (bool condition, string msg) {Throwifnullorempty (msg, "MSG");
   if (condition) {throw new ArgumentException (msg); }///<summary>///If the specified directory exists the file is thrown FileNotFoundException exception///</summary>///<param name= "files Ytemobject "></param>///<param name=" ArgumentName "></param> public static void Throwifdoesnotex
   IST (filesysteminfo filesytemobject, String argumentname) {throwifnull (Filesytemobject, "filesytemobject");
   Throwifnullorempty (ArgumentName, "argumentname"); if (!filesytemobject.exists) {throw new FileNotFoundException ("' {0} ' not found".)
   Fi (Filesytemobject.fullname));
  } public static string Fi (this string format, params object[] args) {return formatinvariant (format, args);
  ///<summary>///Format strings and use <see cref= "CultureInfo.InvariantCulture" > Invariant culture </see>. </summary>///<remarks>///<para>This should be the "B" > "B" > "" used for any string that is displayed to the user.  It means log///messages, exception messages, and other types of information that do not allow them to enter the user interface, or do not///to the user at any point; .</para>///</remarks> public static string
   Formatinvariant (This string format, params object[] args) {throwifnull (format, "format"); return 0 = = args. Length? Format:string.
  Format (cultureinfo.invariantculture, format, args); ///<summary>///If time is not DATETIMEKIND.UTC, throw ArgumentException exception///</summary>///<param name= "a Rgumenttovalidate "></param>///<param name=" ArgumentName "></param> public static void Throwifno
   TUTC (DateTime argumenttovalidate, String argumentname) {throwifnullorempty (ArgumentName, "argumentname"); if (Argumenttovalidate.kind!= datetimekind.utc) {throw new ArgumentException ("You must Pass" UTC DateTime value
   ", ArgumentName);
 }
  }
 }

    2. Enumeration extension methods:

 public static class Enumextensions {///<summary>///get name///</summary>///<param name= "E" &G t;</param>///<returns></returns> public static string GetName (this Enum e) {return ENUM.GETN
  Ame (E.gettype (), E); ///<summary>///Get first name and value///</summary>///<param name= "Enumtype" > Enum </param>///< param name= "Lowerfirstletter" > Conversion to lowercase </param>///<returns></returns> public static dictionary& Lt;string, int> getnamesandvalues (this Type enumtype, bool lowerfirstletter) {//Because the extension method is actually a call to a static method, the CLR does not generate code pairs
   The value of the expression that invokes the method is checked for null value argumentvalidator.throwifnull (enumtype, "enumtype");
   Gets the enumeration name array var names = Enum.getnames (enumtype);
   Gets an array of enumerated values var values = enum.getvalues (enumtype); var d = new dictionary<string, int> (names.
   Length); for (var i = 0; i < names. Length; i++) {var name = Lowerfirstletter? Names[i].
Lowerfirstletter (): Names[i];    D[name] = Convert.ToInt32 (values.
   GetValue (i));
  return D; ///<summary>///Convert to lowercase///</summary>///<param name= "s" ></param>///<returns&gt
   ;</returns> public static string Lowerfirstletter (this string s) {Argumentvalidator.throwifnull (S, "s"); return char.
  Tolowerinvariant (S[0]) + s.substring (1); }
 }

Five. Summary:

In this paper, the extension method is mainly used to explain the rules, how to declare, how to use, and how to extend the meaning of the method and the principle of the extension method is simply solved. And at the end of this article, we give an enumerated extension method code.

The above is the entire content of this article, I hope to help you, but also hope that a lot of support cloud Habitat community!

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.