`
varsoft
  • 浏览: 2429800 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

[原创]深入理解C# 3.x的新特性(2):Extension Method - Part I

阅读更多
在C#3.0中,引入了一些列新的特性,比如: Implicitly typed local variable, Extension method,Lambda expression, Object initializer, Anonymous type, Implicitly typed array, Query expression, Expression tree. 个人觉得在这一系列新特性的,最具创新意义的还是Extension method,它从根本上解决了这样的问题:在保持现有Type原封不动的情况下对其进行扩展,你可以在对Type的定义不做任何变动的情况下,为之添加所需的方法成员。在继《深入理解C# 3.0的新特性(1): Anonymous Type 》之后,在这篇文章中,我将介绍我自己对Extension method这个新特性的理解。

一、Prototype in JavaScript

为了说明Extension method到底是为了解决怎样的问题,我首先给出一个类似的、大家都比较熟悉的应用:JavaScript 中的Prototype。

比如我们在JS通过function定义了一个Vector class,代表一个2维向量。

functionVector(x,y)
{
this.x=x;
this.y=y;
}

现在我们需要在不改变Vector定义的前提下,为之添加相关的进行向量运算的Method。比如我们现在需要添加一个进行两个向量相加运算的adds方法。在JS中,我们很容易通过Prototype实现这一功能:

Vector.prototype.adds=function(v)
{
if(vinstanceofVector)
{
returnnewVector(this.x+v.x,this.y+v.y);
}

else
{
alert(
"InvalidVectorobject!");
}

}

那么,通过添加上面的一段代码,我们完全可以把adds方法作为Vector的一个方法成员。现在我们可以这样的方式来写代码:

varv=newVector(1,2);
v
=v.adds(v);
alert(
"x="+v.x+",y="+v.y);

Extension Method之于C# 3.0就如同Prototype之于JavaScript

二、如何在C# 2.0中解决Type的扩展性

我们一个完全一样的问题从弱类型、解释型的编程语言JavaScript迁移到C#这种强类型、编译型的语言上来。我们先看看在不能借助Extension Method这一新特性的C# 2.0中,我们是如何解决这一问题。

我们先来看看如何对一个Interface进行扩张。假设我们有如下的一个IVector interface的定义:

publicinterfaceIVector
{
doubleX{get;set;}
doubleY{get;set;}
}

我们希望的是如何对这个Interface进行扩展,为之添加一个Adds Method执行向量相加的运算。我们唯一的解决方案就是直接在这个Interface中添加一个Adds成员:

publicinterfaceIVector
{
doubleX{get;set;}
doubleY{get;set;}
IVectorAdds(IVectorvector);
}

由于Interface和实现它的Type的紧密联系:所以实现了某个Interface的Type必须实现该Interface的所有方法。所以,我们添加了Adds Method,将导致所有实现它的Type的重新定义和编译,在很多情况下,这种代价我们是负担不起的:比如在系统的后期维护阶段,对系统的进行局部和全部的重新编译,将很有可以导致一个正常运行的系统崩溃。Interface的这种局限性在面向抽象设计和编程中应该得到充分的考虑,这也是我们在很多情况下宁愿使用Abstract Class的一个主要原因。

上面说到了对Interface的扩展,会出现必须实现Interface的Type进行改动的风险。我想有人会说,对Class尽心扩展就不会出现这样的情况了吧。不错,Class的继承性确保我们在Parent class添加的Public/Protect能被Child Class继承。比如:如果Vector是一个Super Class:

publicclassVector
{
privatedouble_x;
privatedouble_y;

publicdoubleX
{
get{returnthis._x;}
set{this._x=value;}
}


publicdoubleY
{
get{returnthis._y;}
set{this._y=value;}
}

}

如果我们在Vector Class中添加一个Adds Method,所有的Child Class都不会受到影响。

但是在很多情况下,对于我们需要扩展的Interface或者是Type,我们是完全不能做任何改动。比如,某个Type定义在一个由第三方提供的Assembly中。在现有的情况下,对于这样的需求我们将无能为力。我们常用的方法就自己定义的Class去继承这个需要扩展,将需要添加的成员定义在我们自己定义的Class中,如果对于一个Sealed Class又该如何呢?即便不是Sealed Class,这作用方式也没有完成我们预定的要求:我们要求的是对这个不能变动的Type进行扩展,也就是所这个不能变动的Type的Instance具有我们添加的对象。

如果你在完全了解Extension Method的前提下听到这样的要求:我们要对一个Type或者Interface进行扩展,却不允许我们修改它。这个要求确实有点苛刻。但是,不能否认的是,这样需要在现实中的运用是相当广泛的。所以我说,Extension Method在所有提供的新特性中,是具有价值的一个。

三、C# 3.0中如何解决Type的扩展性

理解了我们的具体需要和现有编程语言的局限性后,我们来看看C# 3.0中是如何通过Extension Method解决这个问题的。

简单地说Extension Method是一个定义在Static Class的一个特殊的Static Method。之所以说这个Static Method特别,是因为Extension Method不但能按照Static Method的语法进行调用,还能按照Instance Method的语法进行调用。

我们还是先来看例子,首先是我们需要进行扩展的Vector Type的定义:

publicclassVector
{
privatedouble_x;
privatedouble_y;

publicdoubleX
{
get{returnthis._x;}
set{this._x=value;}
}


publicdoubleY
{
get{returnthis._y;}
set{this._y=value;}
}

}

在不对Vector Class的定义进行更新的前提下,我们把需要添加的Adds方法定义在一个Static Class中:

publicstaticclassExtension
{
publicstaticVectorAdds(thisVectorp,Vectorp1)
{
returnnewVector{X=p.X+p1.X,Y=p.Y+p1.Y};
}

}

这个Extension Method:Adds是一个Static方法。和一般的Static方法不同的是:在第一个参数前添加了一个this 关键字。这是在C# 3.0中定义Extension Method而引入的关键字。添加了这样一个关键字就意味着在调用该方法的时候这个标记有this的参数可以前置,从而允许我们向调用一般Instance Method的方式来调用这个Static Method。比如:

classProgram
{
staticvoidMain(string[]args)
{
varv
=newVector{X=1,Y=2};
v
=v.Adds(v);
Console.WriteLine(
"v.X={0}andv.Y={1}",v.X,v.Y);
}

}

注:this关键字只能用于标记第一个参数。

通过上面的介绍,我们知道在C# 3.0如何通过定义Extension Method在不对Type作任何修改的前提下对Type进行扩展。至于Extension Method的本质:C# Compiler在编译Extension Method时会做怎样处理;在最终被编译成的Assembly中相关的IL具有怎样的特征;Extension Method的优先级,如果有兴趣,可以参考《[原创]深入理解C# 3.0的新特性(2):Extension Method - Part II》,此外在第二部分中,我会给出一个完整的Sample:通过Extension Method定义一个形如LINQ中常见的Operator,完成基于LINQ的查询功能。

C# 3.x相关内容:
[原创]深入理解C# 3.x的新特性(1):Anonymous Type
[原创]深入理解C# 3.x的新特性(2):Extension Method - Part I
[原创]深入理解C# 3.x的新特性(2):Extension Method - Part II
[原创]深入理解C# 3.x的新特性(3):从Delegate、Anonymous Method到Lambda Expression
[原创]深入理解C# 3.x的新特性(4):Automatically Implemented Property
[原创]深入理解C# 3.x的新特性(5):Object Initializer 和 Collection Initializer

分享到:
评论

相关推荐

    C# 7 and .NET Core: Modern Cross-Platform Development - Second Edition

    C# 7 and .NET Core: Modern Cross-Platform Development - Second Edition by Mark J. Price English | 24 Mar. 2017 | ASIN: B01N8UG78Q | 594 Pages | AZW3 | 23.26 MB Modern Cross-Platform Development ...

    深入理解C# 第3版.zip

    深入理解C# 第3版,高清PDF,绝对原版

    《深入浅出C#》中文版

    《深入浅出C#》中文版 《深入浅出C#》中文版.part3.rar ----------------------------------------满意请留言!------------------------------------------

    深入理解C# 中文第三版

    在第2版的基础上,《深入理解C#(第3版)》新增了C# 5的新特性——异步,并更新了随着技术的发展,已经不再适用的内容,确保整本书能达到读者期望的高标准。 如果你略微了解一点C#,就可无障碍地阅读《深入理解C#(第3...

    C# 电子白板软件源码(WinForm & WPF)

    C# 实现的电子白板软件,包括 WinForm 和 WPF 两个版本的项目,其中 WinForm 版本使用的是 GDI+,WPF 版本使用的是 DrawingVisual。使用了面向对象的设计思维,还有一些项目实践的经验体现,值得新手学习。代码实现...

    深入理解C# 第3版 高清中文版有目录

    在第2版的基础上,《深入理解C#(第3版)》新增了C# 5的新特性——异步,并更新了随着技术的发展,已经不再适用的内容,确保整本书能达到读者期望的高标准。 如果你略微了解一点C#,就可无障碍地阅读《深入理解C#(第3...

    Aspose Total for NET 2013.09.10 最新破解(danny_su 大作)

    现免费提供大家:) This package contains the following .NET Components: - Aspose.BarCode for .NET v5.7.0.0 - Aspose.Cells for .NET v7.5.3.0 - Aspose.Diagram for .NET v3.4.0.0 - Aspose.Email for .NET v...

    深入理解C# 高清 pdf

    深入理解C# 高清 pdf 非扫描 C# 1 中定˦的ֵ̖集合ۋ

    深入理解C#(第2版)

    《深入理解C#(第2版)》是C#领域不可多得的经典著作。作者在详尽地展示C#各个知识点的同时,更注重从现象中挖掘本质。本书深入探索了C#的核心概念和经典特性,并将这些特性融入到代码中,让读者能够真正领会到C#之...

    C#windows.part2--total 3

    C#windows.part2--total 3

    [C#] 深入理解 C# 第3版 英文版

    [Manning Publications] 深入理解 C# 第3版 英文版 [Manning Publications] C# in Depth 3rd Edition E Book ☆ 出版信息:☆ [作者信息] Jon Skeet [出版机构] Manning Publications [出版日期] 2013年09月...

    支持【kindle】《深入理解C#》(第3版图)灵程序设计丛书.mobi

    本书支持kindle,《深入理解C#(第3版)》是C#领域不可多得的经典著作。作者在详尽地展示C#各个知识点的同时,更注重从现象中挖掘本质。本书深入探索了C#的核心概念和经典特性,并将这些特性融入到代码中,让读者能够...

    C#做的串口RS232通信程序

    自己用C#做的RS232通讯程序...看看吧...里面纠正了网上很多看似可以的程序段...这也是自己实验过的... ----------------2020/06/08 18:16 更新分割线--------------- 已经有十年了 居然还有人需要 那就开始免费吧 ...

    深入理解C#+中文+第2版PDF 扫描高清版

    《深入理解C#(第2版)》是C#领域不可多得的经典著作。作者在详尽地展示C#各个知识点的同时,更注重从现象中挖掘本质。本书深入探索了C#的核心概念和经典特性,并将这些特性融入到代码中,让读者能够真正领会到C#之...

    深入理解C#(第二版)part2

    深入理解C#(第二版)part2 有导航 方便阅读。扫描版,但是很清晰

    北大青鸟5.0 2期 深入.NET平台和C#编程.part3.rar

    深入.NET平台和C#编程.part3.rar

    深入理解C#中文-第2版.part2.rar

    深入理解C#中文-第2版 希望对大家的学习有帮助。

    C# 让程序带参数运行,如:app.exe -a -c

    C# 让程序带参数运行,如:app.exe -a -c C# 让程序带参数运行,如:app.exe -a -c C# 让程序带参数运行,如:app.exe -a -c C# 让程序带参数运行,如:app.exe -a -c C# 让程序带参数运行,如:app.exe -a -c

    深入理解C#(C# in Depth, 2nd)

    《深入理解c#:第2版》是c# 领域不可多得的经典著作。作者在详尽地展示c# 各个知识点的同时,更注重从现象中挖掘本质。 经典中的经典哇 本人花钱在淘宝买的,版权问题我就没管了哈。但是本人也没敢独享,发出来有...

    深入理解C# 第3版 [(英)斯基特著][2014.04]part1

    深入理解C# 第3版 [(英)斯基特著][人民邮电出版社][2014.04][490页]

Global site tag (gtag.js) - Google Analytics