如何解决扩展库中的扩展方法歧义错误



假设我有一个扩展方法。

public static string DoSomething(this IInterfaceA @this) ...

public static string DoSomething(this IInterfaceB @this) ...

但是,如果我有一个实现这两个接口的类,那么对于扩展库来说,是否可以指示它应该更喜欢哪一个?

简短回答-不,不可能。

长话短说:扩展方法只是一个接受参数并包含关键字this的静态方法。Intellisense扫描代码以找到所有扩展方法,并为我们提供语法糖,允许在类的实例上调用它们,与普通方法相同。

另一方面,接口描述对象行为,用于根据对象的作用对对象进行分组、分离/隔离:

IBird { void Fly(); }
IBug { void Crawl(); }
class Parrot : IBird {}
class Ant : IBug {}

如果我们有这样的东西:

IGlidingBird { void Fly(); }  // and
IFlappingBird { void Fly(); }

然后很可能我们的设计很糟糕,因为作为虚拟方法容器的接口不应该知道它的实际实现

在示例代码中,您将看到一个编译时错误:"以下方法之间的调用不明确…"。

可以将对象强制转换为其中一种接口类型,让编译器知道要使用哪些方法:

((IInterfaceA)instance).DoSomething()
((IInterfaceB)instance).DoSomething()

这可能是一个停下来思考是否有可能改变设计并完全避免这个问题的好时机。

是的,这是可能的。

您需要声明另一个具有泛型的扩展方法,该泛型将两种类型都作为约束。


public static string DoSomething<T>(this T @this) where T : IInterfaceA, IInterfaceB
{  
...
}

现在不会有歧义,因为编译器更喜欢最受约束的扩展方法而不是其他扩展方法。

您可以将实例变量传递到静态扩展方法中,用变量替换此参数。

例如:

命名空间系统{公共静态类ExceptionExtensions{公共静态字符串GetFullExceptionMessage(此Exception ex({…

实现为

{catch(异常ex({System.ExceptionExtensions.GetFullExceptionMessage(ex(;