Framework3.0学习笔记(二): 新特性(2)

 新特性(2):

5、扩展方法

  如果需要给一个现有类增加一个方法,我们会怎么做?一般会用两种方式:一、修改原来类的代码,增加这个方法。二、创建一个派生类,在派生类中定义这个方法。修改原有代码肯定是我们不愿意做的,而且 我们也不一定有修改 代码的权限。而创建派生类并不是真正向原类型中添加方法, 要使用这个方法 ,我们不得不创建的新实例。有没有一种方式,在不用修改原代码的情况下,直接给这个类添加方法呢?C#3.0中为我们提供了一种方式,这就是扩展方法。

  利用扩展方法我们不但能向以前定义的类中添加新方法,而且可以为Framework中定义的原始类型和接口任意添加方法,是不是很新奇啊?没错,这看起来是很有意思,也很方便。其实微软在3.0中已经为许多基础接口增加了扩展方法 ,比如Enumerable(可枚举的)接口中的OrderBy(排序方法)。在LINQ中也很常见,比如标准查询运算符。在Visual Studio的智能感知中, 扩展方法 前面会有个蓝色向下箭头

下面介绍一下扩展方法的实现,先看一个例子

定义:

namespace ExtensionMethods
{
      public static class MyExtensions
      {
            public static int WordCount(this String str)
           {
                  return str.Split(new char[] { ' ', '.', '?' },StringSplitOptions.RemoveEmptyEntries).Length;
           }
     }
}

调用:

using ExtensionMethods;    // 引用命名空间
string s = "Hello Extension Methods";
int i = s.WordCount();

  上面在命名空间 ExtensionMethods中,定义了一个静态类 MyExtensions,实现了静态方法 WordCount,用来获取字符串中包含的单词数量。实现过程是将传进来的字符串参数用空格、点或问号分割为数组,并返数组回元素个数。方法需要一个String参数,但参数类型前面怎么有个"this"啊?这就表明这个方法是this后面 类型(String)的扩展方法。

  从上面的例子可以看出,扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用,调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异。 由于扩展方法必须定义在外部的非泛型静态类中,所以在其他命名空间中调用时,需要引用这个静态类的命名空间,这个命名空间可以看做是扩展方法的作用域。这点其实也很好,我们可以在不同的命名空间定义同名的扩展方法,执行不同的实现,根据需要分别调用。

  扩展方法在实现上其实与实例方法是不同的, 扩展方法是在 编译器生成中间语言(IL)时转换为静态方法调用 ,而且无法访问它们所扩展的类型中的私有变量,所以不会真正违反封装原则。

加载顺序: 当编译器遇到方法调用时,它首先在该类型的实例方法中寻找匹配的方法。如果未找到任何匹配方法,编译器将搜索为该类型定义的任何扩展方法,并且绑定到它找到的第一个扩展方法。

使用时还要注意:

1、扩展方法可以用来扩展类或接口,但不能被重写。
2、编译时,扩展方法的优先级总是比类型本身中定义的实例方法低。换句话说,如果某个类型具有一个名为Process(int i) 的方法,而您有一个具有相同签名的扩展方法,则编译器总是绑定到该实例方法。因此, 与接口或类方法具有相同名称和签名的扩展方法永远不会被调用。
3、在同一命名空间中不能重复定义( 签名 )相同的 扩展方法。

 

 

6、分部方法定义

  在Framework2.0中增加了分布类的定义,3.0中对于方法也增加了分布定义,同样使用partial关键字。

  分部方法声明由两个部分组成:定义和实现。它们可以位于分部类的不同部分中,也可以位于同一部分中。如果不存在实现声明,则编译器将优化定义声明和对方法的所有调用,在编译时移除未提供该实现的方法以及对方法的所有调用 ,并且不会产生运行时开销 。如果调用了未实现的方法,也不会导致编译时错误或运行时错误。分部方法使类的某个部分的实施者能够定义方法(类似于事件),类的另一部分的实施者可以决定是否实现该方法。

例子:

    public partial class Employee
    {
        // 定义方法
        partial void MakeAsManager();
        // 调用方法
        public void Test()
        {
            MakeAsManager();
        }
    }
    public partial class Employee
    {
        partial void MakeAsManager()
        {
            Console.WriteLine("Employee.MakeAsManager()");
        }
    }

这个很简单 ,但在使用时还是要注意几点:

1.分部方法声明必须以上下文关键字partial 开头,并且方法必须返回void。
2.分部方法可以有ref 参数,但不能有out 参数。
3.分部方法为隐式private 方法,因此不能为virtual 方法。
4.分部方法不能为extern 方法,因为主体的存在确定了方法是在定义还是在实现。
5.分部方法可以有static 和unsafe 修饰符。
6.分部方法可以为泛型的。约束将放在定义分部方法声明上,但也可以选择重复放在实现声明上。参数和类型参数名称在实现声明和定义声明中不必相同。
7.不能将委托转换为分部方法。

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值