在 C# 中是否可以使用内部 AND 受保护成员?
Is an internal AND protected member possible in C#?
考虑以下 classes:
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
完全封装了 VehicleList
和 CoverageList
的功能,所以我想将那些 class 标记为 internal
。问题是它们是 public
class 的 protected
字段的类型。如果我将这些字段标记为 protected internal
,那么它们就是 protected
或 internal
。我真正需要的是它们是 protected
和 internal
(protected
在程序集内优先)。您可以看到 Quote
(它有一个 internal
构造函数)和它的子 class(它们是 sealed
)都不能扩展到程序集之外。我已经想出如何使用 public 接口实现所需的功能,但想确保没有更简洁的方法。
尽管 .NET 运行时支持此概念 ("FamilyAndAssembly"),但 C# 目前不支持。
这是以 private protected 访问修饰符的形式针对 C# 6.0 提出的,但该功能已被删除。
更新: private protected
已添加到 C# 7.2。
作为附录:
如果你不想使用接口并且 - 如你所见 - 没有 C# 支持来实现该目标,记住:你总是可以使用 反射做那种很奇怪的事情。
您可以将字段设置为 private
并使用反射,您可以从任何您想要的地方分配新值,确保来自同一程序集中的派生 类。
我怀疑您派生的 classes 是否需要直接访问 Quote
的字段。
I am asking if there is a way to achieve the desired functionality without using public interfaces.
我认为您可以安全地将字段上的修饰符更改为 private
并让派生的 classes 通过 [=13] 间接 操作字段 =] 方法在您的 Quote
基础 class 中定义。不需要额外的 public 接口。
下面是它的外观示例:
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 {}
此替代方案实现了 间接 将 VehicleList
和 CoverageList
仅 暴露给派生 [=32] 的目标=]属于同一个程序集的 es。
考虑以下 classes:
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
完全封装了 VehicleList
和 CoverageList
的功能,所以我想将那些 class 标记为 internal
。问题是它们是 public
class 的 protected
字段的类型。如果我将这些字段标记为 protected internal
,那么它们就是 protected
或 internal
。我真正需要的是它们是 protected
和 internal
(protected
在程序集内优先)。您可以看到 Quote
(它有一个 internal
构造函数)和它的子 class(它们是 sealed
)都不能扩展到程序集之外。我已经想出如何使用 public 接口实现所需的功能,但想确保没有更简洁的方法。
尽管 .NET 运行时支持此概念 ("FamilyAndAssembly"),但 C# 目前不支持。
这是以 private protected 访问修饰符的形式针对 C# 6.0 提出的,但该功能已被删除。
更新: private protected
已添加到 C# 7.2。
作为附录: 如果你不想使用接口并且 - 如你所见 - 没有 C# 支持来实现该目标,记住:你总是可以使用 反射做那种很奇怪的事情。
您可以将字段设置为 private
并使用反射,您可以从任何您想要的地方分配新值,确保来自同一程序集中的派生 类。
我怀疑您派生的 classes 是否需要直接访问 Quote
的字段。
I am asking if there is a way to achieve the desired functionality without using public interfaces.
我认为您可以安全地将字段上的修饰符更改为 private
并让派生的 classes 通过 [=13] 间接 操作字段 =] 方法在您的 Quote
基础 class 中定义。不需要额外的 public 接口。
下面是它的外观示例:
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 {}
此替代方案实现了 间接 将 VehicleList
和 CoverageList
仅 暴露给派生 [=32] 的目标=]属于同一个程序集的 es。