C#语法糖: 扩展方法(常用)
今天继续分享C#4.0语法糖的扩展方法,这个方法也是我本人比较喜欢的方法。大家先想想比如我们以前写的原始类型不能满足现在的需求,而需要在该类型中添加新的方法来实现时大家会怎么做。我先说一下我没有学习到这个知识点之前做的方法:
最笨的办法就是修改原来的类型,然后添加一个方法来达到需求的变更,如下代码所示:
1 public class KuozFF 2 3 { 4 5 public void NormalMethod() 6 7 { 8 9 Console.WriteLine("我是原始方法"); 10 11 } 12 13 public void ExtensionMethod() 14 15 { 16 17 Console.WriteLine("我是扩展方法"); 18 19 } 20 21 }
调用方法:
1 KuozFF method=new KuozFF (); 2 3 method.NormalMethod(); 4 5 method.ExtensionMethod(); 6 7 Console.ReadLine();
输出效果如下:
但是比如说别人给你的是一个dll文件,你没有办法修改,但是你想在该类中添加你的方法怎么办?
自己写一个类,然后该类继承自原始类,代码如下:
1 public class KuozFF 2 3 { 4 5 public void NormalMethod() 6 7 { 8 9 Console.WriteLine("我是原始方法"); 10 11 } 12 13 14 15 } 16 17 18 19 public class MYKZFF : KuozFF 20 21 { 22 23 public void ExtensionMethod() 24 25 { 26 27 Console.WriteLine("我是扩展方法"); 28 29 } 30 31 }
调用代码如下:
1 MYKZFF method=new MYKZFF(); 2 3 method.NormalMethod(); 4 5 method.ExtensionMethod(); 6 7 Console.ReadLine();
效果如下:
以上结果可以看出效果是一样的,但是有的人他不想写继承类,也不想修改源代码怎么办?这时候就扩展方法诞生了!我先看看官方解释吧:
扩展方法:使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。 对于用 C# 编写的客户端代码,调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异
这是微软MSN上的解释,我们直接看代码,扩展方法是长什么样吧:
1 public class KuozFF 2 3 { 4 5 public void NormalMethod() 6 7 { 8 9 Console.WriteLine("我是原始方法"); 10 11 } 12 13 14 15 } 16 17 18 19 public static class ExtensionClass 20 21 { 22 23 public static void ExtensionMethod(this KuozFF k) 24 25 { 26 27 Console.WriteLine("我是扩展方法"); 28 29 } 30 31 }
调用代码如下:
1 KuozFF method=new KuozFF(); 2 3 method.NormalMethod(); 4 5 method.ExtensionMethod(); 6 7 Console.ReadLine();
输出结果:
从上面代码可以看出我们客户端调用时无需关心扩展方法在哪儿写的,你只要实例化原始类,扩展方法自动会有的。
扩展方法在C#4.0中是无处不在的,下面我们看看C#内置的扩展方法来更深刻的了解一下:
1 public static class Enumerable 2 3 { 4 5 public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate); 6 7 public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate); 8 9 public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector); 10 11 public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult> selector); 12 13 }
以上就是微软IEnumerable类的扩展方法,所以我们平时用的时候方法后面点.后就能出来怎么多丰富的where,select等方法是扩展方法起的作用。这里只是拿出一点扩展方法来展示了一下。
下面我们写一下string类扩展方法,我们以前判断一个字符串是否null或空时,用系统内置方法string. IsNullOrEmpty(s),我们把这个方法做成扩展方法演示一下:
1 public static class Demo1 2 3 { 4 5 public static bool IsNullOrEmpty(this string s) 6 7 { 8 9 return string.IsNullOrEmpty(s); 10 11 } 12 13 }
调用代码如下:
1 string temp = "12"; 2 3 bool result = temp.IsNullOrEmpty(); 4 5 Console.WriteLine(result); 6 7 Console.ReadLine();
输出结果:
从调用代码可以看出string本身是没有IsNullOrEmpty()方法的,通过我们自己写扩展方法有了该方法。
大家可以在自己的方法或者对系统类的扩展可以写一下,以便在日后的编码过程中给自己提供方便。
扩展方法注意事项:
1、它至少有一个参数;
2、第一个参数必须附加 this 关键字;
3、第一个参数不能有任何其他修饰符(out/ref)
4、第一个参数不能是指针类型
5、 C# 只支持扩展方法,不支持扩展属性、扩展事件等;
6、 扩展方法的命名空间可以使用 namespace System ,但不推荐;
7、 定义扩展方法的类是静态类;
今天就写到这里吧!谢谢朋友们的支持!
附带 [C#小技巧收集]将字符串转换成List<T>
有时需要将一个字符串分隔后,转换成指定类型的数组或List<T>,比如服务器端收到提交的一组checkbox的值,可能是一个ID串,类似:56,657,0,1,2,3,4,5,6,7,8,需要将它转成一个int数组或List<T>再进行后续处理。
在将字符串转换成List<T>中看到了关于这个的讨论,整理如下。
我们可用Array.ConvertAll 泛型方法来实现,代码如下:
string str = "56,657,0,1,2,3,4,5,6,7,8"; int[] arrInt = Array.ConvertAll<string, int>(str.Split(','), s => int.Parse(s)); foreach (int i in arrInt) Console.WriteLine(i);
或者,我们想用到一些“奇技淫巧”,比如将这功能做成string的扩展方法:
public static List<T> ToList<T>(this string str, char split, Converter<string, T> convertHandler) { if (string.IsNullOrEmpty(str)) { return new List<T>(); } else { string[] arr = str.Split(split); T[] Tarr = Array.ConvertAll(arr, convertHandler); return new List<T>(Tarr); } }
调用方法:
List<int> intList = str.ToList<int>(',', s => int.Parse(s));