C# 扩展方法笔记 ——让代码更优雅的方式

扩展方法并不能从效率或者技术上对代码产生影响,但是可以让代码更优雅也更好看,这可能是我目前觉得最有用的地方。


我们从一个例子来看:首先假设你有一个类,存放三个double类型数据

    public sealed class Data
    {
        public double d1, d2, d3;
        public Data(double D1,double D2,double D3)
        { 
            d1 = D1;
            d2 = D2;
            d3 = D3;
        }
        public double Sum()
        {
            return d1 + d2 + d3;
        }
    }

这是一个非常有限的类,但假设你想让他拥有更多的方法,如方法返回这三个数的平均数。那么一般有几种办法实现这个额外的功能。

  1. 如果你有源代码并可以修改这个类,你只需要为这个类增加一个方法
  2. 如果你不能修改这个类(如这个类在一个第三方类库中),那么只要它不是密封的,你就能把它作为一个基类并派生一个类,在派生类实现这个额外的方法。

然而如果不能访问代码或者该类是密封的,你就没法用上述方法实现,你就不得不在另一个类中实现该类的公有成员实现这样的方法。

    public class UglyWay
    {
        public static double Average(Data data)
        {
            return data.Sum() / 3;
        }
    }

然后你就可以在main函数中这么调用:

            Data data = new Data(3, 4, 5);
            Console.WriteLine($"Average: {UglyWay.Average(data)}");

尽管上面的方法也不错,但是如果能在实例自身上调用该方法,而不是创建一个作用于它的类的实例,将会更优雅。区别如下:

ExtendMyData.Average(data)    //静态形式
data.Average();     //实例形式

扩展方法允许你使用第二种形式。先看扩展方法的代码:

    public static class ExtendData
    {
        public static double Average(this Data data)
        {
            return data.Sum() / 3;
        }
        public static Data PrintInfo(this Data data)
        {
            Console.WriteLine($"d1: {data.d1}\td2: {data.d2}\td3: {data.d3}");
            return data;
        }
        //public static double Getd1(this Data data)
        //{
        //    return data.d1;
        //}

    }

这里我写了2个扩展方法(注意扩展方法的参数形式),一个是返回平均数,一个是打印数据信息,其中打印信息后还返回了参数本身,这么做可以实现连续调用:

            Data data = new Data(3, 4, 5);
         //   Console.WriteLine($"Average: {UglyWay.Average(data)}");

            Console.WriteLine(data.PrintInfo().Average());

输出如下:

d1: 3   d2: 4   d3: 5
4

这么做可以实现类似于管道操作,而且理论上可以无限调用。

小结

  1. 扩展方法必须声明在静态类中
  2. 本身必须被声明为static,必须在参数中包括关键字this和它所扩展的类的名称,且作为第一个参数类型。

值得说明的是,扩展方法不会修改原始类的封装性,当你把Data类中的成员声明为私有方法时,无论你怎么扩展都无法直接访问到那三个成员,也就无法将其打印出来。

细心的你在使用Linq的时候,用鼠标点击linq的扩展方法就会出现类似的形式。一旦当你添加了扩展方法,你就可以像使用.net内部方法一样使用这些方法(智能提示会把这些方法加入),因为你还可以扩展.net内部的方法,如为string类扩展你自己的方法。
 

你可能感兴趣的:(c#)