微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

界面的可访问性

如何解决界面的可访问性

最近对 C# 8.0 中的接口进行了更改,我对可访问性应该如何工作感到有些困惑(它们现在在接口上有效,但以前无效)。

这个看似简单的例子并不像您期望的那样工作:

public interface IFoo
{
    public string Bar { get; internal set; }
}

public class Foo : IFoo
{
    public string Bar { get; internal set; } //Error - Non-public accessor "Bar.set" cannot implement accessor from interface IFoo
}

我似乎可以为 IFoo 接口获得的唯一“工作”代码是:

public interface IFoo
{
    public string Bar { get; internal set; }
}

public class Foo : IFoo
{
    string IFoo.Bar { get; set; }
}

换句话说,接口必须显式实现。

为什么第一个例子无效?为什么这种情况需要显式实现?

解决方法

我的解释,我有一些猜测:

有一条旧规则,如果您不想将接口成员实现为 public 类成员,那么您必须使用显式实现。这允许使规定的接口成员“难以访问”,因为在您的 实现中,它们不适合公共使用。请注意,即使如此,实现仍然是 public

这似乎也适用于现在可以声明他们自己的接口部分,其可见性低于公众,现在似乎是:any member of an interface that *isn't fully public* or that you *don't want to implement as public* must use explicit implementation。注意:我没有这方面的消息来源,我是从我所看到的情况中提取出来的。

由于您的财产只是“半公开”,显然所有财产都属于该规则。

然后还有另一个规则,引用自documentation

显式接口实现没有访问修饰符,因为它不能作为定义它的类型的成员访问。相反,它只能在通过接口实例调用时访问。

这解释了为什么一旦您使用显式实现(强制或不强制),您就不能添加自己的访问修饰符,因为接口定义了适用的访问修饰符(如果省略,则默认为 public)。

这样做的后果

要访问公共 getter,所有客户端代码都需要使用 IFoo

  • var f = new Foo(); var x = ((IFoo)f).Bar; // 有效
  • IFoo f = new Foo(); var x = f.Bar; // 有效
  • var x = new Foo().Bar; // 不编译

是否值得将这一要求强加给您的来电者由您来决定。


如果需要,那么我看到了两种避免该要求的方法,第一种方法意味着将内部 setter 排除在界面之外,只将其放入 Foo,然后使用 setter 进行编码必须使用 Foo 作为变量类型,不能使用 IFoo,而使用 getter 的代码可以为所欲为:

public interface IFoo
{
    public string Bar { get; }                // no setter (and you can omit `public`)
}

public class Foo : IFoo
{
    public string Bar { get; internal set; }  // add internal setter as class member
}

第二种方式,接口中有internal void SetBar(string value),现在所有使用SetBar()的代码都必须使用IFoo作为变量类型,使用getter的代码可以为所欲为:

public interface IFoo
{
    public string Bar { get; }
    internal void SetBar(string value);
}

public class Foo : IFoo
{
    public string Bar { get; private set; }          // add private setter as class member
    void IFoo.SetBar(string value) { Bar = value; }  // use private setter
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。