博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#3.0扩展方法学习篇
阅读量:6340 次
发布时间:2019-06-22

本文共 6076 字,大约阅读时间需要 20 分钟。

 什么是类的扩展方法

扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。

MSDN

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type.

传统的模式下如果想为一个类型(class)添加一个额外的自定义的特殊的逻辑上,或者业务上的新方法时,你必须重新定义的一个类型来继承原有的的方法,用继承类或者接口,但是有些用sealed修饰的,这时候就无法被继承,例如String,值类型,sealed修饰的类。

扩展方法是C#3.0这个版本提出来的。解决了必须由继承才能扩展的某个类的弊端,最重要的一点就是很好用。

平时在我们使用的过程中也经常的见到,如
这其中的OrderBy方法就是扩展方法。
MSDN

注意:

扩展方法必须在非嵌套、非泛型的静态类中定义。

Note that it is defined inside a non-nested<非嵌套>, non-generic<非泛型的> static<静态> class:

扩展方法的规则有以下几点:

  • 扩展方法必须是扩展方法必须是非嵌套、非泛型的静态类中定义的;
  • 扩展方法的第一个参数要用this关键字修饰;
  • 第一个方法参数不能有ref 或则out关键字修饰的参数;
扩展方法的调用有两个步骤
  1. 引用项目的命名空间;
  2. 参数调用两种;
  • 和传统的调用方法一样使用<ExtendClass>.<ExtendClassMethod>(参数,参数+?)
  • <参数类型>.<ExtendClassMethod>(参数+?)
高级点的应用
    在编译时绑定扩展方法<MSDN>
    你可以使用扩展方法来扩展一个类和接口,而不需要去重写他们
1 // Define an interface named IMyInterface.  2 namespace DefineIMyInterface  3 {  4     using System;  5   6     publicinterface IMyInterface  7     {  8         // Any class that implements IMyInterface must define a method  9         // that matches the following signature. 10         void MethodB(); 11     } 12 } 13  14  15 // Define extension methods for IMyInterface. 16 namespace Extensions 17 { 18     using System; 19     using DefineIMyInterface; 20  21     // The following extension methods can be accessed by instances of any  22     // class that implements IMyInterface. 23     publicstaticclass Extension 24     { 25         publicstaticvoid MethodA(this IMyInterface myInterface, int i) 26         { 27             Console.WriteLine 28                 ("Extension.MethodA(this IMyInterface myInterface, int i)"); 29         } 30  31         publicstaticvoid MethodA(this IMyInterface myInterface, string s) 32         { 33             Console.WriteLine 34                 ("Extension.MethodA(this IMyInterface myInterface, string s)"); 35         } 36  37         // This method is never called in ExtensionMethodsDemo1, because each  38         // of the three classes A, B, and C implements a method named MethodB 39         // that has a matching signature. 40         publicstaticvoid MethodB(this IMyInterface myInterface) 41         { 42             Console.WriteLine 43                 ("Extension.MethodB(this IMyInterface myInterface)"); 44         } 45     } 46 } 47  48  49 // Define three classes that implement IMyInterface, and then use them to test 50 // the extension methods. 51 namespace ExtensionMethodsDemo1 52 { 53     using System; 54     using Extensions; 55     using DefineIMyInterface; 56  57     class A : IMyInterface 58     { 59         publicvoid MethodB() { Console.WriteLine("A.MethodB()"); } 60     } 61  62     class B : IMyInterface 63     { 64         publicvoid MethodB() { Console.WriteLine("B.MethodB()"); } 65         publicvoid MethodA(int i) { Console.WriteLine("B.MethodA(int i)"); } 66     } 67  68     class C : IMyInterface 69     { 70         publicvoid MethodB() { Console.WriteLine("C.MethodB()"); } 71         publicvoid MethodA(object obj) 72         { 73             Console.WriteLine("C.MethodA(object obj)"); 74         } 75     } 76  77     class ExtMethodDemo 78     { 79         staticvoid Main(string[] args) 80         { 81             // Declare an instance of class A, class B, and class C. 82             A a = new A(); 83             B b = new B(); 84             C c = new C(); 85  86             // For a, b, and c, call the following methods://      -- MethodA with an int argument//      -- MethodA with a string argument//      -- MethodB with no argument.// A contains no MethodA, so each call to MethodA resolves to // the extension method that has a matching signature. 87             a.MethodA(1);           // Extension.MethodA(object, int) 88             a.MethodA("hello");     // Extension.MethodA(object, string)// A has a method that matches the signature of the following call// to MethodB. 89             a.MethodB();            // A.MethodB()// B has methods that match the signatures of the following// method calls. 90             b.MethodA(1);           // B.MethodA(int) 91             b.MethodB();            // B.MethodB()// B has no matching method for the following call, but // class Extension does. 92             b.MethodA("hello");     // Extension.MethodA(object, string)// C contains an instance method that matches each of the following// method calls. 93             c.MethodA(1);           // C.MethodA(object) 94             c.MethodA("hello");     // C.MethodA(object) 95             c.MethodB();            // C.MethodB() 96         } 97     } 98 } 99 /* Output:100     Extension.MethodA(this IMyInterface myInterface, int i)101     Extension.MethodA(this IMyInterface myInterface, string s)102     A.MethodB()103     B.MethodA(int i)104     B.MethodB()105     Extension.MethodA(this IMyInterface myInterface, string s)106     C.MethodA(object obj)107     C.MethodA(object obj)108     C.MethodB()109  */

 

编译器是如何发现扩展方法的
c# 3.0编译器看到某个类的调用用法时,先是从该类的实例方法中进行查找,如果没有找到与调用方法同名并参数一致的实例方法,再从所有导入的命名空间中查找是否有合适的扩展方法,并将变量类型匹配到扩展类型。
这只是我们的理解是这样一个过程,如果在同一个命名空间下,编译器则会直接用当前命名空间下符合条件的对应方法,让我看下下ILDasm.exe.
如果不是同一个程序集的命名空间可以在MANIFEST清单文件里看出。

总结的结果

方法的调用次序 类型的实例方法--->当前命名空间下的扩展方法--->导入的其他命名空间扩展方法。

引发疑问

在空引用上调用实例方法或静态方法时会抛出NullReferenceException异常?那么在类调用扩展方法时会出现异常吗?(不使用类中的一些属性或方法,强调调用)

        public static void NullUse(this TestExtend sextend)
        {
            Console.WriteLine("NUll used Method");
        }
分析:在空的类型上定义扩展方法不出现NullReferenceException,只是把空这个引用当成参数传入静态方法,
扩展方法 静态方法
TestExtend sExtend=null;
            sExtend.NullUse();
TestExtend sExtend=null;
NullUse.(sExtend);
 
 
 
从ILDASM能看出我们猜想的正确性
Notice

可能引发的子类污染的问题例如

        public static bool isNull(this 
object str)  
        {
            return str == null;
        }

你本来只想扩展TestExtend 这个类的方法,由于你要使用iSNull这个类型的扩展结果传入参数(object),结果导致所有的object 类型都扩展了这个方法,这会带来可怕的后果。

所以在扩展一个类型的方法时,要从确定类型扩展。尽量避免从父类去扩展。

有什么不对的或者错误的地方希望大家给予指正,谢谢

我的开发环境VS2015

DEMO的下载  【http://pan.baidu.com/s/1bY51P8】

 

转载于:https://www.cnblogs.com/knightlilz/p/5335562.html

你可能感兴趣的文章
小公司职场不是“切糕”
查看>>
play工程部署到云服务器
查看>>
ListView 取消点击效果
查看>>
CentOS 6.5下编译安装新版LNMP
查看>>
Android Picasso
查看>>
top命令
查看>>
javascript的作用域
查看>>
新形势下初创B2B行业网站如何经营
查看>>
初心大陆-----python宝典 第五章之列表
查看>>
sysbench使用笔记
查看>>
有关电子商务信息的介绍
查看>>
NFC·(近距离无线通讯技术)
查看>>
多线程基础(三)NSThread基础
查看>>
PHP的学习--Traits新特性
查看>>
ubuntu下,py2,py3共存,/usr/bin/python: No module named virtualenvwrapper错误解决方法
查看>>
Ext.form.field.Number numberfield
查看>>
Linux文件夹分析
查看>>
解决部分月份绩效无法显示的问题:timestamp\union al\autocommit等的用法
查看>>
nginx 域名跳转 Nginx跳转自动到带www域名规则配置、nginx多域名向主域名跳转
查看>>
man openstack >>1.txt
查看>>