本文主要以下面几个方面来详细讲解扩展方法:在C#3.0之前没有扩展方法的状态(或者你不会使用不知道扩展方法的时候)、扩展方法的语法及怎么使用、怎么正确的使用扩展方法;

一、首先说一下在C#3.0之前没有扩展方法的状态(或者你不会使用不知道扩展方法的时候)

1、大家在项目中肯定遇到类似这样的需求且项目很多地方都会用到:1.需要对一个对象进行可空判断;2、对一个集合或者对象进行序列化;3、时间格式转换;4、List与DataTabel之前转换等等。

我想在没有扩展方法之前大家基本上都是做一个类似common的静态公共静态类,写一些静态方法供项目各个调用调用 如:

 public static  class Common
{
/// <summary>
/// 判断是否为Null或者空
/// </summary>
/// <param name="obj">对象</param>
/// <returns></returns>
public static bool IsNullOrEmpty( object obj)
{
if (obj == null)
return true;
else
{
string objStr = obj.ToString();
return string.IsNullOrEmpty(objStr);
}
}
}

其他类调用公共方法

 static void Main(string[] args)
{
string str = "lxsh";
Common.IsNullOrEmpty(str);
}

通过这样也能完成上面所说的几个需求,但是让人感觉上端一直要显示依赖Common这个静态类,项目中就会大量充斥着这样的代码,看起来不那么简洁,而且也不利于后期的链式语法编程;

2、有时也会遇到这样的情况:你想对某个类型加一些行为(方法),但你不能改变该类型的本身,因为是别人的代码,遇到这样情况你可能会增加一个继承接口,或者一个抽象类,或者通过代理模式封装一次,这样显然能达到目的但都很麻烦;

以上解决办法都是在没有使用扩展方法之前的解决方案,当你学会了扩展方法,你可能会有更好的选择;

二、 接下来我们来说一下扩展方法的语法及使用

1、扩展方法必须具备以下几个特征:

  • 必须是在非嵌套的、非泛型的静态类中
  • 必须在静态类中的静态方法
  • 至少要有一个参数
  • 第一个参数的前缀必须加this关键字且不能有任何修饰符(如:ref,out)且参数类型不能为指针

例如:

 public static partial class Extensions
{ public static string ObjectToJSON(this object obj)
{
return JsonConvert.SerializeObject(obj, new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
}
/// <summary>
/// 判断是否为Null或者空
/// </summary>
/// <param name="obj">对象</param>
/// <returns></returns>
public static bool IsNullOrEmpty(this object obj)
{
if (obj == null)
return true;
else
{
string objStr = obj.ToString();
return string.IsNullOrEmpty(objStr);
}
} }

2、怎么使用扩展方法:

先引用扩展方法静态类所在的命名空间,引用完成后,在调用的时候它在你对应类型实例上面有”智能感知“提示

3、扩展方法是怎么被发现调用的

如果在using命令,将扩展方法引用到代码中,扩展方法可以像类一下不加限制地在代码中使用。如果编译器认为一个表达试好像要使用一个实例方法,但没有找到与这个方法调用兼容的实例方法,就会查找一个合适的扩展方法。它会检查导入的所有命名空间和当前命名空间中所有的扩展方法,并匹配那些从表达式类型到扩展类型存在隐式转换的扩展方法;

简单一句话讲:编译器首先会查看这类型(包括父类)有没有对应的该实例方法,如果有该实例方法他就不会执行扩展方法,如果没有它就会找对应的扩展方法执行;

假如有一个 student类,它有一个实例方法say,再给他加一个扩展方法say

  public  class Student
{
public void Say()
{
Console.WriteLine("我是实例方法");
}
} public static class Extensions
{
public static void Say(this Student student)
{
Console.WriteLine("我是扩展方法");
} }
  static void Main(string[] args)
{
Student student = new Student();
student.Say(); Console.ReadKey();
}

执行结果为:

还有一种情况,对子类和父类同时加了一个一样的扩展方法,且都引用了他们名词空间,优先调用子类的扩展方法(同样适用于接口父子关系)

  public class Person
{
}
public class Student:Person
{
public void Say()
{
Console.WriteLine("我是实例方法");
}
} public static class Extensions
{
public static void Say(this Student student)
{
Console.WriteLine("我是扩展方法");
}
public static void GetName(this Student student)
{
Console.WriteLine("我是子类扩展方法");
}
public static void GetName(this Person student)
{
Console.WriteLine("我是父类扩展方法");
} }
  static void Main(string[] args)
{
Student student = new Student();
student.Say();
student.GetName();
Console.ReadKey();
}

执行结果:

三、怎么正确的使用扩展方法(建议)

接下来简单讲一下怎么正确使用扩展方法:

1.如果在项目中使用扩展方法,首先需要要项目成员都熟悉扩展方法的使用

2.将扩展方法单独放到一个单独的命名空间里,可有效的防止被误用,建议扩展方法所属扩展类尽量用partial类(如针对Object的扩展方法命名Extensions.Object、针对string的扩展方法命名Extensions.String),方便代码维护

例如:Extensions.Object、Extensions.String

namespace Lucky.Proect.Core.Extensions
{
public static partial class Extensions
{ public static string ObjectToJSON(this object obj)
{
return JsonConvert.SerializeObject(obj, new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
}
/// <summary>
/// 判断是否为Null或者空
/// </summary>
/// <param name="obj">对象</param>
/// <returns></returns>
public static bool IsNullOrEmpty(this object obj)
{
if (obj == null)
return true;
else
{
string objStr = obj.ToString();
return string.IsNullOrEmpty(objStr);
}
} }
}
namespace Lucky.Proect.Core.Extensions
{
public static partial class Extensions
{
[DebuggerStepThrough] //该特性是用在方法前面的,在想要跳过的方法前面加上
public static T FromJson<T>(this string jsonStr)
{
return string.IsNullOrEmpty(jsonStr) ? default(T) : JsonConvert.DeserializeObject<T>(jsonStr);
}
/// <summary>
/// 指示指定的字符串是 null、空或者仅由空白字符组成。
/// </summary>
[DebuggerStepThrough] //该特性是用在方法前面的,在想要跳过的方法前面加上
public static bool IsNullOrWhiteSpace(this string value)
{
return string.IsNullOrWhiteSpace(value);
}
/// <summary>
/// 将Json字符串转为DataTable
/// </summary>
/// <param name="jsonStr">Json字符串</param>
/// <returns></returns>
public static DataTable ToDataTable(this string jsonStr)
{
return jsonStr == null ? null : JsonConvert.DeserializeObject<DataTable>(jsonStr);
}
}
}

3.尽量不在在object上面写太多的扩展方法,写之前要多加思考,不然在项目使用中任何类型智能提示出现一推扩展方法,看起来比较杂乱,针对int的扩展方法应该写在int类型上,针对datetime的扩展方法应该写在datetime类型上不应该都写在object类型上

4.如果方法名在扩展类型中已经使用,就不要再用这个名称了,因为写了也无效;

学习Linq之前必须要了解的扩展方法的更多相关文章

  1. Linq分组操作之GroupBy,GroupJoin扩展方法源码分析

    Linq分组操作之GroupBy,GroupJoin扩展方法源码分析 一. GroupBy 解释: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值. 查询表达式: var ...

  2. C# LiNq的语法以及常用的扩展方法

    首先先来扯一下,这篇博文是我第一次写的,主要是我的一些摘录,希望对大家有所帮助. Linq的基础 •LINQ(读音link):Linq To SQL(过时).Linq To Object.Linq T ...

  3. ASP.Net MVC开发基础学习笔记:二、HtmlHelper与扩展方法

    一.一个功能强大的页面开发辅助类—HtmlHelper初步了解 1.1 有失必有得 在ASP.Net MVC中微软并没有提供类似服务器端控件那种开发方式,毕竟微软的MVC就是传统的请求处理响应的回归. ...

  4. LinQ—扩展方法

    概述 本节主要解说扩展方法,涉及LinQ的详细知识不多. 扩展方法的描写叙述 .net framework为编程人员提供了非常多的类,非常多的方法,可是,不论.net framework在类中为我们提 ...

  5. C#高级知识点概要(3) - 特性、自动属性、对象集合初始化器、扩展方法、Lambda表达式和Linq查询

    1.特性(Attributes) 特性(Attributes),MSDN的定义是:公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型.字段.方法 ...

  6. Linq快速入门——扩展方法

    Linq为我们提供了许多扩展方法,方便我们对数据源进行操作(Where,Select...).即使你不了解算法,也能使用Linq当回牛人.扩展方法本质并不是什么高深的技术,说白了就是一个Static静 ...

  7. c#写扩展方法

    学习MVC时,学会了写扩展方法,用起来很方便. 01 using System; 02 using System.Collections.Generic; 03 using System.Linq; ...

  8. 给string定义一个扩展方法

    创建一个 static 的类,并且里面的方法也必须是static的,第一个参数是被扩展的对象,必须标注为this,使用时,必须保证namespace using进来了. 实例: using Syste ...

  9. LINQ学习系列-----1.3 扩展方法

    这篇内容继续接着昨天的Lambda表达式的源码继续下去.昨天讲了Lambda表达式,此篇讲扩展方法,这两点都是Linq带来的新特性.    一.扩展方法介绍   废话不多说,先上源码截图: 上图中Ge ...

随机推荐

  1. DDL创建数据库,表以及约束(极客时间学习笔记)

    DDL DDL是DBMS的核心组件,是SQL的重要组成部分. DDL的正确性和稳定性是整个SQL发型的重要基础. DDL的基础语法及设计工具 DDL的英文是Data Definition Langua ...

  2. Jmeter在chrome浏览器中录制脚本

    利用blazemeter插件可以录制chrome浏览器中的操作,并生成jmx文件,导入到jmeter中使用 1.  下载blazemeter 地址:https://pan.baidu.com/s/1V ...

  3. 3-8 pivot操作

      数据透视表¶ In [1]: import pandas as pd excelample=pd.DataFrame({'Month':["January","Jan ...

  4. Centos 7 下yum搭建lnmp环境(yum安装方式)

    我们都知道linux下安装软件主要有三种方式: 1.源码编译安装,即下载软件源代码,利用gcc g++ make 等编译工具进行编译安装: 此方式的优点:可以指定软件版本,可选择性好:编译时可以手动指 ...

  5. Ubuntu下搭建Kubernetes集群(4)--部署K8S Dashboard

    K8S Dashboard是官方的一个基于WEB的用户界面,专门用来管理K8S集群,并可展示集群的状态.K8S集群安装好后默认没有包含Dashboard,我们需要额外创建它. 首先我们执行命令: wg ...

  6. 解决Error: ENOENT: no such file or directory, scandir 'xxx\node-sass\vendor'

      解决方案是执行以下方法: npm rebuild node-sass

  7. Shiro密码加密

    Shiro密码加密 相关类 org.apache.shiro.authc.credential.CredentialsMatcher org.apache.shiro.authc.credential ...

  8. (day47)jQuery

    目录 一.初识jQuery (一)jQuery介绍 (二)版本介绍 (三)jQuery对象 (四)相关网站 (五)基础语法 二.查找标签 (一)基本选择器 (1)id选择器 (2)标签选择器 (3)c ...

  9. LG5367 「模板」康托展开 康托展开

    问题描述 LG5367 题解 康托展开公式: \[ans=1+(\sum_{i=1}^{n}{a_i})\times(n-i)!\] 用树状数组维护一下\(\sum\)里面的东西,前缀积维护后面的东西 ...

  10. leetcode 561. 数组拆分 I

    为了理解这种方法,让我们从不同的角度来看待问题.我们需要形成数组元​​素的配对,使得这种配对中最小的总和最大.因此,我们可以查看选择配对中最小值的操作,比如 (a,b)(a,b) 可能会产生的最大损失 ...