【问题标题】:Is an internal AND protected member possible in C#? [duplicate]在 C# 中是否可以使用内部和受保护的成员? [复制]
【发布时间】:2015-11-23 18:24:12
【问题描述】:

考虑以下类:

public class Vehicle { ... }
public class Coverage { ... }

public class VehicleList : IEnumerable<Vehicle> { ... }
public class CoverageList : IEnumerable<Coverage> { ... }

public abstract class Quote
{
    protected VehicleList vehicles;
    protected CoverageList coverages;

    internal Quote() { ... }

    public IReadOnlyCollection<Vehicle> Vehicles
    {
        get { return this.vehicles.AsReadOnly(); }
    }
    public IReadOnlyCollection<Coverage> Coverages
    {
        get { return this.coverages.AsReadOnly(); }
    }

    ...
}

public sealed class OhQuote : Quote
{
    //needs to access protected fields
    ...
}
public sealed class InQuote : Quote { ... }
public sealed class MiQuote : Quote { ... }

Quote 完全封装了VehicleListCoverageList 的功能,所以我想将这些类标记为internal。问题是它们是protected 类的protected 字段的类型。如果我将这些字段标记为protected internal,那么它们就是protectedinternal。我真正需要的是让他们成为protectedinternalprotected 在程序集中优先)。您可以看到Quote(具有internal 构造函数)及其子类(sealed)都不能在程序集之外扩展。我已经想出了如何使用公共接口实现所需的功能,但想确保没有更简洁的方法。

【问题讨论】:

  • 创建一个封装受保护字段的内部属性
  • @Gusman 仍然会将受保护的字段公开给程序集中类的消费者。
  • 抱歉,但我不太明白您的要求,受保护的字段将始终对任何消费者可见,无论它在哪里定义,并且内部属性将始终可见到同一个程序集中的所有类,所以程序集中的消费者可以看到“受保护的内部”,那么你想要什么?
  • Okoko,现在我明白了,它应该只有通过在你的程序集中继承类才能看到,对吧?
  • @Gusman 是的,没错。

标签: c# oop inheritance protected


【解决方案1】:

虽然 .NET 运行时支持这个概念(“FamilyAndAssembly”),但 C# 目前不支持。

这是在 C# 6.0 中以 private protected 访问修饰符的形式提出的,但该功能已被删除。

更新: private protected 已添加到 C# 7.2

【讨论】:

  • 该死的,这正是我要找的。知道为什么该功能被删除了吗?
  • 在这个discussion page上,“nmgafter”表示“我们目前不太可能添加这个新的保护级别,主要是因为我们找不到好的语法。”
  • 有趣。在我看来,不实现某个功能的理由很愚蠢,但我同意 private protected 的语法不太理想。
【解决方案2】:

作为附录: 如果您不想使用接口并且 - 如您所见 - 没有 C# 支持来实现该目标,记住:您始终可以使用 reflection 做那种非常奇怪和奇怪的事情。

您可以将该字段设置为private 并使用反射,您可以从任何您想要的位置分配新值,确保来自同一程序集中的派生类。

【讨论】:

  • 我很感兴趣,你能举个例子说明你是怎么做到的吗?
【解决方案3】:

我质疑您的派生类是否需要直接访问Quote 的字段。

我在问是否有一种方法可以在不使用公共接口的情况下实现所需的功能。

我认为您可以安全地将字段上的修饰符更改为 private 并让派生类通过在您的 Quote 基类中定义的 protected 方法间接操作字段。不需要额外的公共接口。

下面是一个例子:

public class Vehicle {}
public class Coverage {}

// Set these as "internal" as you were hoping for...
internal class VehicleList : IEnumerable<Vehicle>
{
    public void Foo() {}
}

internal class CoverageList : IEnumerable<Coverage>
{
    public void Bar() {}
}

public abstract class Quote
{
    // Mark these as "private"
    private VehicleList vehicles;
    private CoverageList coverages;

    internal Quote() {}

    public IReadOnlyCollection<Vehicle> Vehicles
    {
        get { return this.vehicles.AsReadOnly(); }
    }
    public IReadOnlyCollection<Coverage> Coverages
    {
        get { return this.coverages.AsReadOnly(); }
    }

    // Add protected methods to manipulate the private fields.
    protected void PerformFooOnVehicles()
    {
        this.vehicles.Foo();
    }

    protected void PerformBarOnCoverages()
    {
        this.coverages.Bar();
    }

}

public sealed class OhQuote : Quote
{
    // We now have indirect access to Quote's private fields.
    public void Baz()
    {
        this.PerformBarOnCoverages();
        this.PerformFooOnVehicles();
    }
}
public sealed class InQuote : Quote {}
public sealed class MiQuote : Quote {}

此替代方案实现了间接VehicleListCoverageList暴露给属于同一程序集的派生类的目标。

【讨论】:

    猜你喜欢
    • 2011-07-07
    • 2012-10-09
    • 2012-07-04
    • 1970-01-01
    • 2012-03-27
    • 2012-11-27
    • 2018-10-27
    • 2018-02-11
    • 1970-01-01
    相关资源
    最近更新 更多