【问题标题】:How to resolve ambiguous interface method signatures, occuring when multiple generic type arguments are identical如何解决模棱两可的接口方法签名,当多个泛型类型参数相同时发生
【发布时间】:2015-10-19 01:27:14
【问题描述】:

在下面的例子中,实现类的方法有没有办法明确地告诉编译器它实现了哪个接口成员? 我知道可以解决接口之间的歧义,但这里是在一个接口中。

interface IFoo<A,B>
{
    void Bar(A a);
    void Bar(B b);
}

class Foo : IFoo<string, string>
{
    public void Bar(string a) { }
    public void Bar(string b) { }  // ambiguous signature
}

【问题讨论】:

  • 你误解了接口。你只需要public void Bar(string a) { }。您正在实现接口的 contract,而不是方法定义本身。当A=B 对外部调用者时,两个Bar 定义之间没有区别。它们是一回事。
  • 我不认为你能解决这个问题,因为如果你不使用泛型就没有意义,写下没有泛型,看看会发生什么,也许它可以帮助你理解为什么不可能
  • 为了进一步解释,您的界面显示“任何实现我的人都应实现Bar(A)Bar(B)”。当通过&lt;string, string&gt;时,合约变为“任何实现我的人都应该实现Bar(string)”。
  • @Rob 我不认为我误解了接口。我犯了一个设计错误,没有考虑实现类可以为 A 和 B 传递相同的类型,从而产生了这种签名冲突。我在这里问是因为希望 C# 对方法参数有一些语法方式来指示它们代表的接口参数,例如:public void Bar(string a) where a represents IFoo::A { } 但现在我确定没有,我会制作接口的方法名称独一无二。

标签: c#


【解决方案1】:

我认为你不能只使用一个接口直接解决这个问题,因为在某些情况下方法签名可能会统一。

如果你真的需要这个功能,我认为你必须引入一个由 foo 派生的新接口。

public interface IBar<T>
{
    void Bar(T t);
}

public interface IFoo<A, B> : IBar<A>
{
    void Bar(B b);
}

现在您可以显式实现这两个接口:

public class Foo : IFoo<string, string>
{
    void IFoo<string, string>.Bar(string b)
    {
        Console.WriteLine("IFoo<string, string>.Bar: " + b);
    }

    void IBar<string>.Bar(string t)
    {
        Console.WriteLine("IBar<string>.Bar: " + t);
    }
}

但如果你想使用它,你必须将你的实例强制转换为特殊接口:

var foo = new Foo();
((IFoo<string, string>)foo).Bar("Hello");
((IBar<string>foo).Bar("World");

按预期打印:

IFoo<string, string>.Bar: Hello
IBar<string>.Bar: World

希望这会对您有所帮助。我认为没有其他方法可以做到这一点。

可以只显式实现一个接口,这样你只需要在你想调用另一个方法时进行转换。

【讨论】:

  • 谢谢。更改界面的成本很高,我试图避免它,但看起来没有办法解决它。我将方法名称更改为 BarA 和 BarB。
【解决方案2】:

你只需要删除重复的行:

interface IFoo<A, B>
{
    void Bar(A a);
    void Bar(B b);
}

class Foo : IFoo<string, string>
{
    public void Bar(string a) { }
}

在这种情况下,void Bar(string a) 的单个实现会实现接口的两种方法。

实际上调用接口要困难得多。你需要反思。

【讨论】:

  • 谢谢。这使代码编译,但它并没有解决问题。 Bar(A)Bar(B) 在语义上是不同的,因此不能用相同的方法实现。如果无法解决歧义,我将不得不更改方法名称。
  • @ArmyNoodles - 是的,这就是你必须做的。
【解决方案3】:

你不能这样做。

Bar() 在这种情况下会模棱两可。考虑将接口方法改为BarA()BarB()

另外,考虑使AB 更有意义的名称(例如,IFoo&lt;TKey, TValue&gt;),那么您的方法可以是BarKey()BarValue()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-08
    相关资源
    最近更新 更多