在C#中,是否可以像在VB.NET中那样使用不同名称的成员来实现接口成员?

13

好的,我提出一个问题,不是为了展示良好的编程实践(这实际上可能被认为是一种不好的做法),而是关于“是否”可以完成。

话虽如此,在VB.NET中,您可以像这样实现接口...

Sub SomeInterfaceMember()
    Implements ISomeInterface.SomeInterfaceMember
End Sub

在C#中,您需要显式地这样做(只能通过接口调用)...
void ISomeInterface.SomeInterfaceMember(){}

更简单地说,可以像这样隐式地进行(在这种情况下,您可以直接调用它或通过接口调用)。
void SomeInterfaceMember(){} // <-- This name matches the interface member

然而,关于VB,您也可以使用任何您想要的名称来为成员执行此操作...
Sub SomeRandomMemberName() // <-- This name doesn't match the interface member
    Implements ISomeInterface.SomeInterfaceMember
End Sub

换句话说,处理实现的方法可以与接口成员名称完全不同。我在想C#中是否有类似的方法。(是的,我知道可以简单地使用显式接口,然后通过另一个具有不同名称的“包装器”成员访问它,但在VB.NET中,你只需使用一个单独的方法即可完成两者。)那么这可以做到吗?

2
这有时是很好的做法。例如,如果您正在实现 IDisposable 并且希望具有一个 Close 方法,则可以使用 Sub Close Implements IDisposable.Dispose 将它们合并为一个方法。简明易读。 - MarkJ
@Supercat,我对你的说法有问题,因为有时你不能在公共接口中使用相同的名称。接口定义仅适用于通过该接口调用某些内容的情况。如果您实现了两个不同的接口,它们共享一个名称但在上下文中意义不同怎么办?当前的解决方法是创建一个包装器,通过接口调用成员,但VB的好处是您不必这样做。实际上,更进一步地说明,如果您的说法是正确的,为什么要允许显式接口定义呢? - Mark A. Donohoe
@MarqueIV:在一个公共方法WoozleClass.Bar()中实现IWoozle.Foo()似乎是一种代码异味。然而,如果名称Foo已经被占用,我认为使用受保护的方法IWoozleFoo()来实现IWoozle.Foo()没有任何问题。在我的看法中,将公共方法Close实现IDisposable.Dispose()使得这两个函数始终表现完全相同,这样做实际上可能会希望允许不同的语义(例如,允许关闭后重新打开但不处理等)。 - supercat
@MarqueIV:我猜我可以想象出一些情况,其中一个实现两个接口的类具有公共名称,这些名称非常清楚地表明它们是特定接口方法的实现(类似于上面的受保护方法),但更常见的是像Dispose/Close这样的建议,我不喜欢这种建议。 - supercat
@Supercat,你刚刚证明了我的观点。在你的例子中,你说:“使公共方法Close实现IDisposable.Dispose()承诺两个函数的行为绝对相同。”没错。这正是我们想要的,也正是重点所在。如果我们希望你在声明中描述的另一部分,“可能经常想要允许发散的语义”,那么我们就不使用这个方法了。事实上你也无法这样做,因为你需要两个单独的实现。再次强调,你在回答问题时争论的观点是无效的。 - Mark A. Donohoe
显示剩余3条评论
2个回答

7
不,C#中不可能实现这个功能。(在VB.NET中也不能“显式实现接口”)

1
我认为我们都可以同意,C#不允许这样做是一件非常好的事情。 - MattDavey
4
@MattDavey:我对这件事情没有强烈的感觉,为什么它是一个“非常好的事情”? 回复:我对此无明显偏见……为什么这是一个“相当不错的事情”呢? - user541686
@MattDavey,我个人认为这并不是一个“好事”。我们有一个名为DesignerContext的基类,我们为程序的各个部分创建其子类。然而,我们应用程序的框架通过IDesignerContextAware接口注入它。我个人发现这非常令人恼火,因为我不能将接口直接附加到ProgramContext(它是DesignerContext类型),这会使事情更易读。我们现在唯一的解决方案需要两个实现...一个叫做implements IDesignerContextAware,另一个叫做ProgramContext,只需委托下去即可。 - Mark A. Donohoe
1
@MattDavey,你没有抓住重点,而@Mehrdad,你没有恰当地解释它。无论在实现接口的类上调用什么方法,接口成员的名称在通过接口调用时都不会改变。如果我有一个实现ILaa的对象Foo,并且Foo有FooMethod实现ILaa.LaaMethod,我可以通过Foo.FooMethod调用该方法,也可以将Foo转换为ILaa,然后调用LaaMethod。我没有改变任何东西或违反任何契约。“Close implements IDisposable.Dispose”是说明这一点有多有用的很好的例子。 - Mark A. Donohoe
2
@MattDavey:行void myInterface.foo()等同于Private Sub SomeRandomJunkA28GWE02() Implements myInterface.foo。名称myInterfacefoo很重要,但名称SomeRandomJunkA28GWE02在某些反射场景之外基本上是无关紧要的。 - supercat
显示剩余6条评论

1

从技术上讲,“可以”做到这一点,通过使用显式实现+调用该实现的公共方法,您可以实现与VB方案基本无法区分的结果。

除了涉及反射的情况外,这实际上最终将是相同的。


1
是的,我知道,因为我在问题本身中确切地说了那个。但那不是我的问题所在。我想知道是否可以像在VB.NET中一样,在C#中用单个语句来实现,但看起来似乎不行。 - Mark A. Donohoe
@MarqueIV 那么这已经确认了吗?你不能在C#中实现吗?看起来很奇怪。是的,我同意这可能是一件好事,只是有趣而已。 - Seabizkit
确认了吗?嗯,我还没有找到任何地方展示如何做到这一点的参考资料。那是最终确定的吗?如果这是在拉斯维加斯,我知道该把我的钱放在哪里! :) - Mark A. Donohoe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接