c# - 受约束的扩展方法产生模棱两可的调用

标签 c# generics

假设我们有两个不相关的接口(interface)

public interface IFirst
{

}

public interface ISecond
{

}

以及具有相同名称但受限于每个接口(interface)的扩展方法。

public static class IFirstExtensions
{
    public static void DoIt<TFirst>(this TFirst model)
        where TFirst : IFirst
    {

    }
}

public static class ISecondExtensions
{
    public static void DoIt<TSecond>(this TSecond model)
        where TSecond : ISecond
    {

    }
}

当我尝试使用 IFirst 实例时:

IFirst first = ...;
first.DoIt();

然后我得到错误:

"CS0121 The call is ambiguous between the following methods or properties: 'IFirstExtensions.DoIt(TFirst)' and 'ISecondExtensions.DoIt(TSecond)'".

这很奇怪。看起来这两种方法在此范围内都是可见的。但如果我给它们取不同的名字,例如:

public static class IFirstExtensions
{
    public static void DoFirst<TFirst>(this TFirst model)
        where TFirst : IFirst
    {

    }
}

public static class ISecondExtensions
{
    public static void DoSecond<TSecond>(this TSecond model)
        where TSecond : ISecond
    {

    }
}

然后约束起作用,第二种方法不可见并引发编译错误:

IFirst first = ...;
first.DoSecond();

所以看起来约束稳定条件在检测歧义和调用时的工作方式不同。但是在 C# 规范中,我发现只有一章与这个主题相关,严格描述了约束是如何工作的。这是编译器中的错误还是我遗漏了什么?

最佳答案

通用约束不是方法签名的一部分。这两种方法在重载解析方面完全相同,因此会产生一个模糊的调用错误。

Specifically, the signature of a method consists of its name, the number of type parameters and the number, modifiers, and types of its formal parameters (C# 5.0 Specification, 10.6 Methods)

For the purposes of signature comparisons any type-parameter-constraints-clauses are ignored, as are the names of the method’s type-parameters, but the number of generic type parameters is relevant (ECMA-334, 25.6.1 Generic method signatures)

说得更清楚一点,当涉及到重载决议时,两种扩展方法都是简单的:

public static void DoFirst<T>(this T model)

另外,请注意该问题不仅仅与扩展方法有关。考虑以下示例,其中在同一类中声明了两个具有相同签名但不同约束的泛型方法:

class Foo
{
    void Bar<T>(Blah blah) where T: Frob { }
    void Bar<T>(Blah blah) where T: Blob { } //CS0111 error
}

你会得到一个编译时错误:

CS0111 Type 'Foo' already defines a member called 'Bar' with the same parameter types.

关于c# - 受约束的扩展方法产生模棱两可的调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45903399/

相关文章:

c# - 数组被C#虚拟机写保护

c# - 通过 WCF 同步本地 SQL Express 数据库

c++ - 难以结合 GP 和 OOP 概念

Java泛型,不能使用任何可迭代对象的参数创建构造函数

c# - 显示希伯来语 sqlplus

c# - 需要简单的 UDP 套接字教程

java - 如何使用泛型参数扩展非静态类?

java - 类型安全 : The expression of type Map[] needs unchecked conversion to conform to Map<String, 对象>[]

c# - 如何在 Windows Phone 8.1 中使用 MediaCapture 设置最大分辨率?

java - 这个错误描述是什么意思?