为什么我可以将继承另一个接口的接口中的方法标记为私有?

lon*_*904 3 c# inheritance private interface

Afaik,在 C# 中,接口中的任何实现方法都必须是公共的。

interface A { void DoA(); }
class B : A { public void DoA() {} }
Run Code Online (Sandbox Code Playgroud)

但如果你继承的接口又继承自另一个接口,那么你可以将基接口方法标记为私有。

interface A1 { void DoA1(); }
interface A2 : A1 { void DoA2(); }
class B : A2
{
    public void DoA2() { } // Still need to be marked as public
    void A1.DoA1() { } // Can be marked as private
    // or I can do this: public void DoA1() { }
}
Run Code Online (Sandbox Code Playgroud)

class MyClass : IEnumerable<SomeType>当我看到一个班级这样做时,我首先注意到这一点。

public IEnumerator<MyType> GetEnumerator() { ... }
private IEnumerator IEnumerable.GetEnumerator() { ... }
Run Code Online (Sandbox Code Playgroud)

为什么这是允许的?为什么我可以将 的实例传递给采用私有B方法的方法?我找不到任何关于此的文档。A1DoA1

Gur*_*ron 6

void A1.DoA1() { }不将方法标记为私有,它是显式接口实现

显式接口实现没有访问修饰符,因为它不能作为定义它的类型的成员进行访问。相反,它只能在通过接口实例调用时进行访问。如果为显式接口实现指定访问修饰符,则会出现编译器错误 CS0106。

ieprivate IEnumerator IEnumerable.GetEnumerator() { ... }甚至不会编译。

为什么这是允许的?为什么我可以将 B 的实例传递给采用 A1 的方法,即使 DoA1 是私有的?

正如前面所描述的,DoA1它不是私有的,也不可能是私有的,因为接口是一个契约,如果类实现了一个接口,它应该满足契约,否则编译应该失败(因此保留了类型安全)。

显式接口实现的用法之一正是这种IEnumerable<T>情况 -IEnumerable<T>扩展IEnumerable并定义具有相同签名的成员(返回类型不是签名的一部分) -GetEnumerator因此为了能够满足这两个契约,需要显式实现。

另一种用法(也可以被认为是有效的IEnumerable<T>)是接口成员“隐藏” - 当开发人员不希望通过实现类型访问某些方法时和/或在接口继承的情况下,当后代接口公开“首选”版本时方法的(例如在IGenericInterface<T> : INonGenericInterfacewith 等场景中IEnumerable)。

但如果你继承的接口又继承自另一个接口,那么你可以将基接口方法标记为私有。

实际上不需要接口继承,接口可以部分(或完全)显式实现:

interface A1 { void DoA1(); void DoA2();}
class B : A1
{
    public void DoA2() { } 
    void A1.DoA1() { } 
}
Run Code Online (Sandbox Code Playgroud)