隐式内部接口实现

Kja*_*ara 3 c# interface implicit-conversion

当我有一个公共界面

public interface IPub { string Foo { get; set; } }
Run Code Online (Sandbox Code Playgroud)

然后我可以通过显式实现这个接口:

public class CFoo : IPub { string IPub.Foo { get; set; } }
Run Code Online (Sandbox Code Playgroud)

或者通过使用public修饰符隐式地:

public class CFoo : IPub { public string Foo { get; set; } }
Run Code Online (Sandbox Code Playgroud)

.有道理:修饰符必须是public因为接口是public.

但是当我有一个内部接口

internal interface IInt { string Bar { get; set; } }
Run Code Online (Sandbox Code Playgroud)

然后我只能明确地实现它:

public class CBar : IInt { string IInt.Bar { get; set; } }
Run Code Online (Sandbox Code Playgroud)

或隐式使用public修饰符:

public class CBar : IInt { public string Bar { get; set; } }
Run Code Online (Sandbox Code Playgroud)

,但不是internal修饰符:

public class CBar : IInt { internal string Bar { get; set; } }
// compiler error:
//     'CBar' does not implement interface member 'IInt.Bar'.
//     'CBar.Bar' cannot implement an interface member
//      because it is not public.
Run Code Online (Sandbox Code Playgroud)

这毫无意义.为什么public只在界面时需要修饰符internal?是否有任何技术原因public必须始终在隐式接口实现中使用,或者C#开发人员是否可以使其不同(不需要更改语言中的许多内容)?

Mar*_*ell 6

修饰符必须是公共的,因为接口是公共的.

虽然这将是一种确定它方式:这不是编译器想要的.对于隐式接口实现(无论接口类型的可见性如何),必须将成员声明为public"ifs","buts"或"maybes"(但实现类型可以是任何可见性级别)

语言设计者绝对可以看到更复杂的规则,但是:由于还有一个显式接口实现的选项,他们可能并不认为有必要这样做.


具体来说,这是规范(v5)中的§18.6.5("接口映射") - 强调我的("I"=接口类型,"M"=成员,"S"=实现类型):

  • 如果S包含与I和M匹配的显式接口成员实现的声明,则此成员是IM的实现
  • 否则,如果S包含与M匹配的非静态公共成员的声明,则此成员是IM的实现如果多个成员匹配,则未指定哪个成员是IM的实现这种情况只有在S时才会发生是一个构造类型,其中泛型类型中声明的两个成员具有不同的签名,但类型参数使它们的签名相同.