关于使用扩展方法的警告

本文介绍了在.NET Framework 2.0中使用VB9扩展方法的风险,特别是在混合.NET版本的环境中可能出现的编译错误。作者分享了实用的扩展方法案例,并提供了避免问题的建议。

Warning About Using Extension Methods

Bug

In an article I published at DevX about some of the new features in VB9, I described how you could use extension methods, which are a new feature available in VB9, even in projects targeted at the .NET 2.0 framework. When I first read about extension methods, my mind began racing through all the features I wish various classes and products had implemented. A short list of the extension methods I implemented and used frequently are described below.

  • IsSomething(Object) and IsNothing(Object): These methods make it easy to check object references.
  • SafeString(String): This method always returns a string. In the event that a string was set to Nothing, it returned String.Empty. An overloaded version of the method also accepted a default value that would be returned when the string was set to Nothing.
  • SafeDBString(SQLDataReader), SafeDBInteger(SQLDataReader), etc: These methods allow safe access to fields returned in a result set. In most cases, when I want to read a string from a database, especially for display, I want an empty string instead of DBNull. This method does this neatly and concisely.

I know there are various ways to implement these methods without using extension methods, but the dot syntax used when you call extension methods appeals to me. The syntax of strMyString.IsNullOrEmpty() seems more natural than String.IsNullOrEmpty(strMyString).

That said, I will offer you a warning that my article referenced above did not mention. If 1) you work in an environment where classes containing plumbing code, business classes, and the like are created, and 2) you have used extension methods created in .NET 2.0 projects, you will find yourself in a sticky situation when (if) you decide to use those classes from a .NET 3.5 project. The problem is caused by duplicate definitions for the ExtensionAttribute: one in your .NET 2.0 project and one in the .NET 3.5 framework.

When you attempt to compile a .NET 3.5 project with references to duplicate ExtensionAttribute definitions, the build output console in Visual Studio doesn't show a specific error. It merely indicates that the build failed. If you attempt to build the project manually using command line tools, the error message looks like the output below.

Microsoft (R) Visual Basic Compiler version 9.0.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved

InternalXmlHelper.vb(9) : error BC30560: 'ExtensionAttribute' is
ambiguous in the namespace 'System.Runtime.CompilerServices'.

<Global.System.Runtime.CompilerServices.ExtensionAttribute()> _
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you have the luxury of upgrading your entire code base to .NET 3.5 at one time, then you will be safe. Simply remove the 'hacked' ExtensionAttribute definition from your code. When the projects are recompiled, references to the ExtensionAttribute will naturally pick up the definition provided in the .NET 3.5 framework.

If you run in a mixed environment, like I do most of the time, then you will run into the problem that the ExtensionAttribute will be defined both in your .NET 2.0 project (as described in the DevX article) and in the .NET 3.5 framework. This will prevent you from compiling any .NET 3.5 projects that reference any of your .NET 2.0 classes that use extension methods. Keep in mind that this means that any project that contains the .NET 2.0 assembly where you 'hacked' a definition for ExtensionAttribute, even if it is an indirect reference (you reference an assembly that references it), cannot be referenced by a .NET 3.5 project until the 'hacked' definition is removed.

Extension methods are still useful in some smaller projects where the entire project will be upgraded to .NET 3.5 at one time. Extension method users beware: if you work in an environment where you have multiple versions of .NET assemblies in use, you are heading into a world of pain.


下面对以上内容进行详细解释

首先,什么是扩展方法?

       扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。对于用 C# 和 Visual Basic 编写的客户端代码,调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异。


再来说说上面文章的意思

       扩展方法在vb9中引入的,并且引入到.net framework 2.0,我常使用的扩展方法有:

       IsSomething(Object) and IsNothing(Object): 易于检查对象引用

       我知道可以有不同的方法来实现上面的功能而不使用这些扩展方法。但是句点语法吸引着我,strMyString.IsNullOrEmpty() 看起来比String.IsNullOrEmpty(strMyString)更自然。

       下面我将谈到使用扩展方法需要注意的问题:如果1)你工作在包含管理代码,业务类或者相似类的环境中;2)你在net 2.0项目中使用扩展方法,你会发现当你在.net 3.5中使用这些类时相当棘手。问题产生的原因扩展属性重复定义:一个定义在.net 2.0项目中,一个定义在.net 3.5框架中。

当你试图编译带有重复属性定义引用的.net 3.5项目时,visual studio不会显示一个特定错误,它几乎不会显示构建失败。如果你试图使用命令行工具编译项目,错误输出如下:

Microsoft (R) Visual Basic Compiler version 9.0.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved

InternalXmlHelper.vb(9) : error BC30560: 'ExtensionAttribute' is
ambiguous in the namespace 'System.Runtime.CompilerServices'.

<Global.System.Runtime.CompilerServices.ExtensionAttribute()> _
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        如果你一次性将整个代码升级到.net 3.5,你将会是安全的。从你的代码中简单的移除“hacked”扩展属性定义。当项目重新编译,使用扩展属性的引用将会自然选择.net 3.5框架中定义的。

       如果你运行一个混合的环境,你将会碰到问题:扩展属性在.net 2.0项目和.net 3.5 框架都有定义。那些使用.net 2.0扩展属性类的.net 3.5项目在编译时会碰到问题。这意味着任何包含“hacked”扩展属性的.net 2.0组件的项目不能被.net 3.5项目所引用,除非“hacked”属性定义被移除。

      扩展方法在一些一次升级到.net 3.5的项目中仍然能够使用。扩展方法使用者请注意:如果你工作在有多个版本.net组件环境中,你将会很头痛。


参考:
http://hi.baidu.com/aspnetchina/blog/item/bb86fd7cd787c51b29388a74.html
http://www.thesoftwaredevotional.com/2009/01/warning-about-using-extension-methods.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值