扩展方法是一个双刃剑,你如果要用扩展方法,就一定得准备碰到别人也用扩展方法,并且万一出现你们都对同一个类进行扩展函数名,参数一样的扩展时候, 会出的各种问题.
说明:以下测试是基于Orcas Beta1环境的测试,VS2008 正式版发布后,也许会发生变化。
如果你对扩展方法不是很熟悉,建议先看我之前的两篇博客:
C#3.0 中的扩展方法 (Extension Methods)
如果我们项目中,在不经意期间,出现了重名的扩展方法,这时候编译器会如何处理呢?这就是本文要探讨的问题。
先说结论:编译器按照下述三个优先级顺序去寻找到底哪个方法被调用到:
假设,我们是在A 命名空间下,调用 类 B 的 C 方法。 类的 C 方法可能是在 D 命名空间下使用扩展方法扩展实现的。
1、类 B 中是否真实存在 C 方法(非扩展方法),如果存在,则调用之,存在时,不考虑是否有扩展,直接进行调用。(这种情况请看我之前的博客:C#3.0 中的扩展方法 (Extension Methods))
2、命名空间 A ,是否存在对C方法的扩展,如果存在,则调用这种情况下的扩展;看示例代码二
3、调用代码中,除了 命名空间 A,还引用了其他命名空间 D和 F。A命名空间没有对C方法进行扩展,则调用D命名空间下的扩展。
特殊情况:
如果 F 和 D 命名空间都对 C 方法进行了扩展,则编译器报错误;看下面的示例代码一
如果 D 和 A命名空间都对 C 方法进行了扩展,则调用 A命名空间下的扩展,编译器不会报错;看示例代码二
示例代码一:
以下代码会编译时报错:
The call is ambiguous between the following methods or properties: 'ConsoleApplication1.MyClass01.DO(int)' and 'ConsoleApplication2.MyClass02.DO(int)
表明 using ConsoleApplication2; using ConsoleApplication1; 导致 ConsoleApplication2 和 ConsoleApplication1 命名空间同级,同级搜索出现重名,报错。
namespace ConsoleApplication2
{
using System;
static class MyClass02
{
internal static void DO(this int i)
{
Console.WriteLine(string.Format("ConsoleApplication2.MyClass02.DO {0}", i));
}
}
}
namespace ConsoleApplication1
{
using System;
static class MyClass01
{
public static void DO(this int i)
{
Console.WriteLine(string.Format("HongJunGuo.MyClass01.DO {0}", i));
}
}
}
namespace HongJunGuo.Test
{
using System;
using ConsoleApplication2;
using ConsoleApplication1;
class Program
{
static void Main(string[] args)
{
int w = 9;
w.DO();
Console.ReadLine();
}
}
}
示例代码二
以下代码返回的信息为 HongJunGuo.MyClass01.DO 9, 标明优先找 本命名空间下的扩展方法。
namespace ConsoleApplication2
{
using System;
static class MyClass02
{
internal static void DO(this int i)
{
Console.WriteLine(string.Format("ConsoleApplication2.MyClass02.DO {0}", i));
}
}
}
namespace HongJunGuo.Test
{
using System;
using ConsoleApplication2;
static class MyClass01
{
public static void DO(this int i)
{
Console.WriteLine(string.Format("HongJunGuo.MyClass01.DO {0}", i));
}
}
class Program
{
static void Main(string[] args)
{
int w = 9;
w.DO();
Console.ReadLine();
}
}
}
特殊情况:如果出现下面的代码:
编译器并不会报错,返回的信息是 ConsoleApplication2.MyClass02.DO , ConsoleApplication2.MyClass02.DO MyObject
原因: 上级命名空间在处理逻辑上跟其他命名空间处理逻辑是一样的.
namespace ConsoleApplication2
{
using System;
using HongJunGuo.Test;
static class MyClass02
{
public static void DO(this int i)
{
Console.WriteLine(string.Format("ConsoleApplication2.MyClass02.DO {0}", i));
}
public static void DO(this MyObject obj)
{
Console.WriteLine("ConsoleApplication2.MyClass02.DO MyObject");
}
}
}
namespace HongJunGuo
{
using System;
using HongJunGuo.Test;
static class MyClass01
{
public static void DO(this int i)
{
Console.WriteLine(string.Format("HongJunGuo.MyClass01.DO {0}", i));
}
public static void DO(this MyObject obj)
{
Console.WriteLine("HongJunGuo.MyClass01.DO MyObject");
}
}
}
namespace HongJunGuo.Test
{
using System;
using ConsoleApplication2;
public class MyObject
{
public MyObject()
{
}
}
class Program
{
static void Main(string[] args)
{
int w = 9;
w.DO();
MyObject obj = new MyObject();
obj.DO();
Console.ReadLine();
}
}
}
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1649494