18.C#扩展方法(十章10.1-10.2)

  今天的话题,我们来聊下扩展方法,自己也真心感叹自己的文笔,那叫一个惨啊,回顾写的文章,看着看着也忘记当时是怀着什么心态写的,哈哈,现代人真心是太随性了,可能也是太冷漠了,接着写的吧,总是会有帮助,也会有收获的。

  扩展方法是从C#3开始出现在我们的眼前,它即有静态方法的优点,也使我们的代码更具可读性,可以像实例方法一样调用静态方法。在扩展方法没有出现前,我们在代码中常常出现静态的工具类(当然,即使现在我们来会使用静态工具类,那都是前人的智慧结晶),如一个字符串帮助类、时间转换工具类。想像一下,当我们得到一个封装好的类库,里面的源代码是不可见,我们只是类库的使用者,但类库的开发者也不是十全十美的思路,总是会有一些遗漏。我们拿简单的来说,比如现在我拿到一份代码,代码中有一个Room类,如下:

1 class Room
2 {
3     public string Name { get; set; }
4 }

  上面的代码是不能修改的,想象一个我们可以使用什么方法给对象的Name属性赋值?我们可以使用实例一个Room对象,直接赋值,但现在我想给Room类加一个SetName的方法,那扩展方法会帮助到我们。如:

 1 static class RoomExt
 2 {
 3     public static void SetName(this Room room, string name)
 4     {
 5         room.Name = name;
 6     }
 7 }
 8 
 9 Room room = new Room();
10 room.Name = "草堂";
11 Console.WriteLine(room.Name);
12 room.SetName("澡堂");
13 Console.WriteLine(room.Name);
14 Console.ReadKey();

  上述代码中,SetName方法就是Room类的扩展方法,可以像调用实例方法一样调用它。Room类的开发者忘记给Room类增加一个SetName方法,那我们就使用扩展方法给Room类加一个方法,调用的方式和实例方法一样。SetName的第一个参数为扩展类型,指定要扩展的类,并使用关键字this,规定而已,请遵守之。方法的修饰符为static,呵呵,遵守之。如果我们写的代码是外部调用的话,请使用public关键字,使用pirvate关键字,那就只能在为其扩展的扩展方法中才能使用。

1 room.SetName("澡堂"); //调用SetName方法,内部会实现为RoomExt.setName(room,"澡堂")

  上面的代码是不是和我们的静态工具一样,是的,使用扩展方法,可以使用代码更具可读性。当然上述的代码只是一个简单使用,在我们正常使用中,自己写的类肯定会加入合适的实例方法,即使是类库的,那也会让类库开发者加一个方法。但如果是微软的开发者没给出合适的方法,没办法,自己加吧。所以扩展方法经常被我们用来扩展系统类型的方法。扩展方法类似静态方法,但它也必须要具有以下的特征:

  1. 它必须在一个非嵌套的、非泛型的静态类中,如RoomExt类
  2. 它至少要有一个参数
  3. 第一个参数不能使用其它修饰符(ref和out)
  4. 第一个参数必须使用this关键字修饰
  5. 第一个参数的类型不能是指针类型

  找到合适的方法

  当我们使用SetName时,会先在实例方法中找,是否有这个方法,如果没有,会从引入的命名空间中找签名符合的方法,也有可能全有重载情况发生,那基于"谁更优"找到方法并执行。

  对空类型进行扩展

  实际上是对object对象进行扩展,如

1 static class objectExt
2 {
3     public static bool IsNull(this object o)
4     {
5         return o == null;
6     }
7 }

  使用如下:

 1 static class objectExt
 2 {
 3     public static bool IsNull(this object o)
 4     {
 5         return o == null;
 6     }
 7 }
 8 
 9 
10 Room room1 = null;
11 Console.WriteLine(room1.IsNull());

  使用是不是很生动,如果你愿意也可以在类中加一个实例方法IsNull,或者使用静态工具来判断一个实例是否为null。实例方法我扩展方法是可以重载的,如

1 class Room
2 {
3     public string Name { get; set; }
4 
5     public bool IsNull()
6     {
7         return this == null;
8     }
9 }

   在Room类中加一个实例方法IsNull,那当调用IsNul时,永远也调用不到扩展方法,记住上面说的"找方法"的顺序。

   请斧正。

原文地址:https://www.cnblogs.com/a2htray/p/4217241.html