接口访问修饰符的困境

3

在我的C#程序中,我有几个自己的接口,我希望保持这些接口只在我的程序集内部可见。

internal interface Doable {
    void DoSomething ();
}

internal interface Informable {
    void SomethingHappened (Doable obj);
}

我还有一个抽象类,不能是internal,它抽象地实现了这两个接口,代码如下。

public abstract class MyAbstractClass : Doable, Informable {
    internal abstract void DoSomething ();
    internal abstract void SomethingHappened (Doable obj);

    // Other methods
}

当我这样做时,会出现一个错误,指出MyAbstractClass没有实现Doable.DoSomething()(以及SomethingHappened(Doable obj))。
我可以将抽象实现的DoSomething()的访问修饰符更改为public(但我一开始并不想这样做),但是SomethingHappened(Doable obj)则是另一回事:它抱怨(理所当然)接口Doable是内部的(因此该方法可能没有public访问修饰符)。
我陷入了困境。我基本上想保留整个程序集中所有类的两个接口及其所有具体实现方法,对外部调用者不知道它们的存在。
想知道如何解决?

3
您可以使用显式接口实现(https://learn.microsoft.com/zh-cn/dotnet/csharp/programming-guide/interfaces/explicit-interface-implementation),并将方法调用转发到一个内部的抽象方法。 - kanders84152
接口是契约。要么公开它们,要么不要签署合同(不要告诉调用者,根本不要将它们添加到公共类中)。那个带有internal abstract成员的public class是一种代码异味。@Servy的答案很好,另一个方法是公开public MyPublicAbstractClass,它包装(而不是继承!)一些internal MyInternalAbstractClass - Sinatr
1
@Sinatr,合同也可以是内部的,没有任何有效的理由不这样做。我不同意代码异味的部分:当需要在装配体内多个对象之间传播和级联对象更改时,存在非常有效的用例,而不让外部知道这一点。访问修饰符会妨碍这一点。 - Najeeb
我的观点是:为什么要暴露internal的东西(你通过使用接口来实现)?为什么调用者需要知道这些呢?看看框架,我不记得有一个类实现了像这样的隐藏接口,因为设计始于创建公共接口。而你却试图创建包含隐藏内容的公共类。为什么?因为一些隐藏方法正在使用公共类的隐藏接口方法吗?所以你试图让那个类扮演两个角色=代码异味。你能给我们展示具体的代码吗?如果你是对的,那么辩论和辩护会更容易。 - Sinatr
2个回答

5

不要将接口实现抽象化,提供一个具体的(显式接口)实现,调用一个内部抽象方法来完成工作。这样可以确保接口不能在公共环境中被调用,只能从当前程序集中访问。


我发誓我最初读到的答案是“从内部接口继承公共接口,并在公共类中实现该接口”。这部分被更改或从未写入吗?如果更改了,是否存在问题? - Sinatr
@Sinatr 如果你在问我是否编辑过这个答案,那么我的回答是没有。 - Servy
void SomethingHappened (Doable obj) 无法重定向到 protected abstract 方法,因为 Doable 参数是 internal。因此实际方法应该是 internal(或 private protected)。 - Ivan Stoev
1
@IvanStoev 它只需要是内部的。已编辑。 - Servy

-1

你应该使用显式实现;

internal interface IDoable
{
    void DoSomething();
}

internal interface Informable
{
    void SomethingHappened(IDoable obj);
}
public class MyClass : IDoable, Informable
{
    void IDoable.DoSomething()
    {
        throw new NotImplementedException();
    }

    void Informable.SomethingHappened(IDoable obj)
    {
        throw new NotImplementedException();
    }
}

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