【问题标题】:Why must an C# interface method implemented in a class be public?为什么类中实现的 C# 接口方法必须是公共的?
【发布时间】:2011-11-06 12:05:40
【问题描述】:

我有一个继承接口的类。在我的类中实现了一个接口成员方法,没有访问修饰符(因此,默认情况下它是 private )。

我收到错误“无法实现接口成员,因为它不是公共的”。

为什么不允许?我不能覆盖可访问性吗?

【问题讨论】:

    标签: c# class inheritance interface


    【解决方案1】:

    这是一个为什么能够覆盖可见性没有意义的示例:

    interface someI
    {
        void doYourWork();
    }
    public class A : someI
    {
        public void doYourWork()
        {
            //...
        }
    }
    
    public class B : someI
    {
        private void doYourWork()
        {
            //...
        }
    }
    void Main()
    {
        List<someI> workers = getWorkers();
        foreach(var worker in workers)
            worker.doYourWork();
    }
    

    当你的工人是 B 型时会发生什么?您正在调用一个方法,就好像它是公共的,但它是一个私有方法。如果你想要这个功能,那它不是真正的私有方法吗?

    如果您只希望它在通过您的界面被引用时是公开的,那么您可以这样定义它:

    public class B : someI
    {
        void someI.doYourWork()
        {
            //...
        }
    }
    

    你最终会得到这个:

    var b = new B();
    b.doYourWork(); // Not accessible
    ((someI)b).doYourWork(); // Accessible
    

    【讨论】:

    • 我建议对于未密封的类,其实现不会暴露具有相同名称和签名的公共类成员的接口应该使用受保护的虚拟成员来实现;不幸的是,在 C# 中最接近的方法是让接口实现简单地调用受保护的虚拟方法。否则,如果派生类重新实现接口,将无法调用父实现。
    • @supercat 也许现在还早,但我不确定我是否在关注你; Otherwise, if a derived class re-implements an interface there will be no way to call the parent implementation 是什么意思?为什么要让受保护的方法实现接口(在这种情况下,您将无法通过接口访问它;仅在派生类中,甚至可能不知道它们正在实现什么接口)
    • 在 vb.net 中,可以说:Protected Overridable Sub DoSomethingImpl() Implements IDoSomething.DoSomething;外部代码只能通过接口调用该方法,但派生类将能够覆盖该方法,并在覆盖范围内调用父方法。在 C# 中,同样能够使用受保护的方法来实现接口会很有用,但负责规范的人员不允许该选项。最接近的方法是使用一种调用受保护方法DoSomethingImpl() 的方法显式实现接口。请注意...
    • ...实现方法的名称可以是DoSomething() 而不是DoSomethingImpl(),但使用以前的名称会阻止派生类公开DoSomething() 方法。
    【解决方案2】:

    方法必须实现public,因为它们必须可以通过接口调用,因此接口可以作为类型访问。

    您有几个选项可以“更改”该方法的可见性。给定:

    public interface IFoo 
    {
        bool IsFoo();
    }
    

    A.实现方法explicitly

    public class Foo : IFoo
    {
        bool IFoo.IsFoo() { return true; }
    }
    

    该方法只能通过接口使用(在这种情况下为IFoo。)

    B.更改界面的可见性

    将接口定义为internal 而不是public。但是,因此,Foo 也必须是 internal

    【讨论】:

    • 在其他语言(例如 vb.net)中,实现接口的方法不需要特定的可访问性。 C# 要求隐式接口实现必须是公共的,因为没有其他关键字或符号表明命名的类成员也应该被视为接口实现。
    【解决方案3】:

    要求接口实现公开只是一个逻辑要求。当你实现一个接口时,你是在告诉编译器“嘿,我在这个接口上实现了每个方法”。因此,将方法设为私有会使其不再可访问 - 并且在逻辑上未实现。接口充当使用您的对象的代码的合同,表示您始终可以调用我的对象的接口中定义的任何方法。如果实现方法是私有的,那就不再适用了。

    如果你想隐藏你的实现,比如 Intellisense,那么你可以简单地像 @Bryan 提到的那样显式地实现该方法。

    【讨论】:

    • “接口充当使用您的对象的代码的合同,说明您始终可以调用我的对象的接口中定义的任何方法。”这并不完全正确。这意味着您可以将类的实例强制转换为接口,然后然后通过接口引用调用接口方法。那是合同,而不是在不首先转换到接口的情况下调用接口方法的能力。当然,您通常应该公开接口方法而不需要强制转换,但这既不是技术要求,也不是逻辑要求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-04
    • 2023-03-13
    • 1970-01-01
    • 2012-12-07
    • 2019-02-17
    相关资源
    最近更新 更多