- 举个例子
链式调用,方法链(method chaining)是面向对象的编程语言中的一种常见语法,可以让开发者在只引用对象一次的情况下,对同一个对象进行多次方法调用。虽然链式调用不包含在23种设计模式,但它是一种常用的代码设计方式。
扩展方法,使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种静态方法,但可以像扩展类型上的实例方法一样进行调用。
在编写代码的时候,使用链式调用可以使代码的行为更加清晰,而扩展方法则可以在不修改原有类型(包括int、string等内置类型)的基础上为类型添加行为。
举个例子,为C#的int、string类型添加方法:
using System;
using System.Text;
namespace ExampleProject
{
class Program
{
static void Main(string[] arg)
{
int num = 1.Plus(40)
.Plus(9)
.Subtract(2)
.Multi(10)
.Divide(2);
string str = "Hello World!".Add(" This is C#.")
.Remove(" World");
Console.WriteLine(num);
Console.WriteLine(str);
}
}
///<summary>
///int类型的扩展方法
///</summary>
public static class class1
{
public static int Plus(this int num1,int num2)
{
return num1+num2;
}
public static int Subtract(this int num1,int num2)
{
return num1-num2;
}
public static int Multi(this int num1,int num2)
{
return num1*num2;
}
public static int Divide(this int num1,int num2)
{
return num1/num2;
}
}
///<summary>
///string类型的扩展方法
///</summary>
public static class class2
{
public static string Add(this string str1,string str2)
{
return str1+str2;
}
public static string Remove(this string str1,string str2)
{
string[] strs = str1.Split(new string[]{str2},StringSplitOptions.RemoveEmptyEntries);
str1 = "";
foreach (var item in strs)
{
str1+=item;
}
return str1;
}
}
}
//输出:
//240
//Hello! This is C#.
- 写一个代码结合查看
/// <summary>
/// EntityFramwork中的链式编程示例
/// </summary>
private void Example1()
{
using (NorthwindEFEntities northwindEFEntities = new NorthwindEFEntities())
{
northwindEFEntities.Employees
.Where(e => e.FirstName.StartsWith("C"))
.Select(e => e.FirstName)
.OrderBy(s => s);
}
}
这一个基本的查询,执行了三个操作:1.查找FristName以C开头的员工;2.取员工的FirstName;3.将名字排序。
- EF中只需要一个语句,通过.将三者链成一个语句。后面还可以链接更多的语句。
下面代码作一些演化:
/// <summary>
/// 链式编程示例2
/// </summary>
private static void Example2()
{
Person person = new Person { Name = "Tom" }
.Run()
.Sing()
.Swim();
}
class Person
{
public string Name { get; set; }
public Person Run()
{
Console.WriteLine("Run");
return this;
}
public Person Swim()
{
Console.WriteLine("Swim");
return this;
}
public Person Sing()
{
Console.WriteLine("Sing");
return this;
}
}
这段代码定义了Peoson类,有三个操作Run、Swim、Sing,操作完成后返回自身this(有返回值是链式编程的关键)。返回自身this好比说执行完操作先别走人,还(可能)有其它操作要去做,如Example2中:先造一个People,先命令ta跑步,跑完先别休息再唱歌,再游泳,游泳完OK了。
链式编程是将多个操作(多行代码)通过点号"."链接在一起成为一句代码。(定义不严密,表达能力好的请给修正一下)
- 以下为常规代码与链式代码的比较:
/// <summary>
/// 链式编程示例3 对比
/// </summary>
private void Example3()
{
//链式代码
Person person = new Person { Name = "Tom" }
.Run()
.Sing()
.Swim()
.Run()
.Sing()
.Swim();
//常规代码
Person person2 = new Person();
person2.Run();
person2.Sing();
person2.Swim();
person2.Run();
person2.Sing();
person2.Swim();
}
为了增强效果,都执行了两轮操作。个人感觉链式代码更加精炼简洁易读。
链式代码要求操作有返回值,但对于很多操作大都是void型,什么也不返回,这样就很难链起来了。当然也有解决办法,可能不太优雅。
- 使用扩展方法解决这个问题,首先引入一个泛型扩展:
/// <summary>
/// 先执行操作,再返回自身
/// </summary>
public static T Do<T>(this T t, Action<T> action)
{
action(t);
return t;
}
下面是调用示例,其中Student类操作都是void型的。
/// <summary>
/// 链式编程示例4
/// </summary>
private static void Example4()
{
new Student { Name = "Tom" }
.Do(s => s.Run())
.Do(s => s.Sing())
.Do(s => s.Sing())
.Do(s => s.Name = "Bob");
}
public class Student
{
public string Name { get; set; }
public void Run() { Console.WriteLine("Run"); }
public void Swim() { Console.WriteLine("Swim"); }
public void Sing() { Console.WriteLine("Sing"); }
}