扩展方法为我们带来了什么

一 发现问题

扩展方法的思考来源于这样的一次经历:在项目中开发程序时,经常这样使用List<T>和Dictionary<K,V>。

<span style="white-space:pre">	</span>    List<string> listTest = new List<string>();
            listTest.ForEach(item =>
                {
                    //方法体略
                });
            Dictionary<string, string> dicTest = new Dictionary<string, string>();
            dicTest.ForEach(item =>
                {
                    //方法体略
                });

二 提出问题

使用的时候也从来没想过,为什么可以这么用,底层是怎么实现的,直到……..

有那么一次,我自己写了个小项目,没有使用平台的类库,突然发现List<T>还可以这么使用,但是Dictionary<K,V>却不可以使用这个方法了,这是怎么回事呢?虽然直接使用迭代器完全可是实现相同的功能,但是本着不讲究是发现问题的源动力,我还是(ˇ?ˇ)
想~一探究竟。

首先F12查看List<T>的底层,发现是这么实现的:

public class List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
    {
<span style="white-space:pre">	</span>public void ForEach(Action<T> action)
        {
            if (action == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }
            int num = this._version;
            for (int i = 0; i < this._size; i++)
            {
                if ((num != this._version) && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
                {
                    break;
                }
                action(this._items[i]);
            }
            if ((num != this._version) && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
            {
                ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
            }
        }
}

三 分析问题

在泛型集合类中,直接写了这个方法的实现,所以可以由对象直接调用这个方法。而Dictionart<K,V>是怎么实现的呢?

<span style="white-space:pre">	</span>public static class IEnumerableExtension
	{
	<span style="white-space:pre">	</span>   public static void ForEach<T>(this IEnumerable<T> data, Action<T> action)
			{
				if (data != null && action != null)
				{
					foreach (T item in data)
					{
						action(item);
					}
				}
			}
	}

这个方法及实现并不是直接写到了字典类或者父类中,原来这是一个扩展类。那么扩展类究竟是怎么回事呢?我们平时会用到吗?应该如何使用呢?

四 理论支持

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

这里的添加带有双引号,原文已经说了,它并不是真正的给类型添加方法,而只是在程序中对它进行了扩展,所以并不需要重新编译和发布底层类库。

好了,理论支持有了,来个实践,选用网上已经实现的例子:string类型有个IsNullOrEmpty方法判断字符串是否为null或为空,比如:

<span style="white-space:pre">	</span>    string strTest = string.Empty;
            bool resultIsNullOrEmpty = strTest.IsNullOrEmpty();

现在,我们还需要进一步判断,赋值内容字符串是否为空字符串。代码如下:

    public static class ExtentdHelper
    {
        public static bool strIsNullOrWhiteSpace(this string str)
        {
            bool strIsNullOrWhiteSpace = false;
            if (string.IsNullOrEmpty(str) || str.Length == 0)
            {
                strIsNullOrWhiteSpace = true;
            }

            return strIsNullOrWhiteSpace;
        }
    }
<span style="white-space:pre">	</span>static void Main(string[] args)
        {
            string strTest = "";
            Console.WriteLine(strTest.IsNullOrWhiteSpace());
            Console.ReadKey();
        }

效果图:

扩展方法的约束:

1
扩展方法必须是静态方法,类必须是静态类,但它是通过实例调用的。

2
第一个参数必须有this关键字,用于确定扩展方法的目的类型。

3可以使用扩展类或接口,但是不能重写扩展方法。

五 解决问题

好了,理论支持有了,我们回头看文章开头小编提出的问题,如何给Dictionary<K,V>编写这个扩展方法呢?

public static class ExtentdHelper
    {
<span style="white-space:pre">	</span>public static void ForEach<T>(this IEnumerable<T> data ,Action<T> action)
        {
            if (data != null && action != null)
            {
                foreach (T item in data)
                {
                    action(item);
                }
            }
        }

    }

调用这个扩展方法:

<span style="white-space:pre">	</span>static void Main(string[] args)
        {
            Dictionary<string, string> dicTest = new Dictionary<string, string>();
            dicTest.Add("1","a");
            dicTest.Add("2","b");
            dicTest.Add("3","c");
            dicTest.ForEach(item =>
                {
                    Console.WriteLine("key: " + item.Key + "   value: " + item.Value);
                });

            Console.ReadKey();
        }

效果图:

六 总结:

扩展方法好处:

1
减少程序中臃肿的代码,使代码更加简洁,更具阅读性。

2
可以在不继承和重写的情况下扩展类型的功能,使程序结构更加灵活。

3
为一些不能不能被继承或修改的类或接口(比如string或第三方控件中的某些类),提供了功能扩展的可能。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-28 21:57:59

扩展方法为我们带来了什么的相关文章

C#的扩展方法解析

在使用面向对象的语言进行项目开发的过程中,较多的会使用到"继承"的特性,但是并非所有的场景都适合使用"继承"特性,在设计模式的一些基本原则中也有较多的提到. 继承的有关特性的使用所带来的问题:对象的继承关系实在编译时就定义好了,所以无法在运行时改变从父类继承的实现.子类的实现与它父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化.当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写它或被其他更适合的类替换,这种依赖关系限制

来看看两种好玩的方法,扩展方法和分布方法

好久没过来扯淡了,话说这年头还有偶遇的事情吗?比如国庆回家的汽车上有个妹子要你qq,要你微信,想着法子跟你聊天,然后睡了一觉,醒来发现 肾不见了?小花絮小花絮,要是肾真没了,也吹不了牛,败不了火了,继续言归正传. 一:扩展方法 说到扩展方法,我想大家都已经再熟悉不过了,也许你的解决方案中有无数个这样的扩展方法,自从有了Linq之后,我们的集合就再也不单纯了. 从下面的Linq类中,所有的方法都扩展在IEnumerable<T>上,恰恰我们的集合都继承于IEnumerable接口下面. 然后我们

用UseMiddleware扩展方法注册中间件类

用UseMiddleware扩展方法注册中间件类 .NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类 0x00 为什么要引入扩展方法 有的中间件功能比较简单,有的则比较复杂,并且依赖其它组件.除了直接用ApplicationBuilder的Use()方法注册中间件外,还可以使用ApplicationBuilder的扩展方法UseMiddleware()注册中间件.这种情况下可以注册类型,这个方法会通过反射解析这个类型,并把它包装成Func<

[读书笔记]C#学习笔记五: C#3.0自动属性,匿名属性及扩展方法

前言 这一章算是看这本书最大的收获了, Lambda表达式让人用着屡试不爽, C#3.0可谓颠覆了我们的代码编写风格. 因为Lambda所需篇幅挺大, 所以先总结C#3.0智能编译器给我们带来的诸多好处, 下一遍会单独介绍Lambda表达式. 这篇主要包括的内容有: 自动属性,隐式类型,对象集合初始化,匿名类型,扩展方法. 下面一起来看下C#3.0 所带来的变化吧. 1,自动实现的属性在C#3.0之前, 定义属性时一般会像下面这样去编写代码: 1 class Person 2 { 3 //定义私

ASP.Net MVC开发基础学习笔记(2):HtmlHelper与扩展方法

一.一个功能强大的页面开发辅助类—HtmlHelper初步了解 1.1 有失必有得 在ASP.Net MVC中微软并没有提供类似服务器端控件那种开发方式,毕竟微软的MVC就是传统的请求处理响应的回归.所以抛弃之前的那种事件响应的模型,抛弃服务器端控件也理所当然. 但是,如果手写Html标签效率又比较低,可重用度比较低.这时,我们该怎样来提高效率呢?首先,经过上篇我们知道可以通过ViewData传递数据,于是我们可以写出以下的Html代码: 1 <input name="UserName&q

.NET 扩展方法 (二)

上一篇随笔 .NET 扩展方法 (一) 已经对 扩展方法有了大致的介绍,这篇算是一个补充,让我们来看一下扩展方法的几个细节: 一.扩展方法具有继承性 当使用扩展方法扩展一个类型的时候,其也扩展了派生类,所以上一篇的遗留问题“如果给object添加一个扩展方法会出现什么效果呢?” 的 答案就是——所有类型都将扩展该方法.object类已经经受住了时间的考验,我们似乎也找不到更合适的理由来扩展object类.从另外的 角度考虑,如果扩展了object类,很有可能会给“智能敏感提示”造成污染,以至于填

ToDictionary()LINQ扩展方法

ToList() 使用IEnumerable<T>并将其转换为 List<T>,那么 ToDictionary()也是类似的.大多数情况ToDictionary()是一个非常方便的方法,将查询的结果(或任何 IEnumerable<T>)转换成一个Dictionary<TKey,TValue>. 关键是您需要定义T如何分别转换TKey和TValue. 如果说我们有超级大的产品列表,希望把它放在一个Dictionary<int, product>,

来看看两种好玩的方法,扩展方法和分部方法

好久没过来扯淡了,话说这年头还有偶遇的事情吗?比如国庆回家的汽车上有个妹子要你qq,要你微信,想着法子跟你聊天,然后睡了一觉,醒来发现 肾不见了?小花絮小花絮,要是肾真没了,也吹不了牛,败不了火了,继续言归正传. 一:扩展方法 说到扩展方法,我想大家都已经再熟悉不过了,也许你的解决方案中有无数个这样的扩展方法,自从有了Linq之后,我们的集合就再也不单纯了. 从下面的Linq类中,所有的方法都扩展在IEnumerable<T>上,恰恰我们的集合都继承于IEnumerable接口下面. 然后我们

C#学习笔记四: C#3.0自动属性&amp;匿名属性及扩展方法

前言 这一章算是看这本书最大的收获了, Lambda表达式让人用着屡试不爽, C#3.0可谓颠覆了我们的代码编写风格. 因为Lambda所需篇幅挺大, 所以先总结C#3.0智能编译器给我们带来的诸多好处, 下一遍会单独介绍Lambda表达式. 这篇主要包括的内容有: 自动属性,隐式类型,对象集合初始化,匿名类型,扩展方法. 下面一起来看下C#3.0 所带来的变化吧. 1,自动实现的属性在C#3.0之前, 定义属性时一般会像下面这样去编写代码: 1 class Person 2 { 3 //定义私