【问题标题】:Is there a way to reach a `protected` member of another object from a derived type?有没有办法从派生类型中访问另一个对象的“受保护”成员?
【发布时间】:2010-09-25 13:29:33
【问题描述】:
class MyBase
{
    protected object PropertyOfBase { get; set; }
}

class MyType : MyBase
{
    void MyMethod(MyBase parameter)
    {
        // I am looking for:
        object p = parameter.PropertyOfBase;  // error CS1540: Cannot access protected member 'MyBase.PropertyOfBase' via a qualifier of type 'MyBase'; the qualifier must be of type 'MyType' (or derived from it)
    }
}

有没有办法从扩展类型中获取类型参数的受保护属性而无需反射?由于扩展类通过其基类型知道该属性,因此如果可能的话,这将是有意义的。

【问题讨论】:

  • 公开而不是保护。
  • 如果我不希望它可以从与 PropertyOfBase 无关的其他类访问怎么办?

标签: c# oop


【解决方案1】:

您还可以将 MyType 声明为 MyBase 的嵌套类(而不是继承),这样您可以在将 MyBase 类作为参数发送时访问私有/受保护的成员

public class MyBase
{
    protected object PropertyOfBase { get; set; }

    public class MyType
    {
        public void MyMethod(MyBase parameter)
        {
            object p = parameter.PropertyOfBase;  
        }
    }
}

要创建 MyType 的实例,只需使用

var t = new MyBase.MyType();
t.MyMethod(new MyBase());

【讨论】:

    【解决方案2】:

    当您从 MyBase 继承时,您可以使用“base”关键字访问标记为“受保护”的所有字段/属性/方法。

    public class MyBase
    {
        protected object PropertyOfBase { get; set; }
    }
    
    public class MyType : MyBase
    {
        void MyMethod()
        {
            object p =  base.PropertyOfBase;
        }
    }
    

    【讨论】:

      【解决方案3】:

      上次遇到类似的问题,我使用的解决方案是在基类中添加一个受保护的静态方法:

      class MyBase
      {
          protected object PropertyOfBase { get; set; }
      
          protected static object GetPropertyOfBaseOf(MyBase obj) 
          {
              return obj.PropertyOfBase;
          }
      }
      
      class MyType : MyBase
      {
          void MyMethod(MyBase parameter)
          {
              object p = GetPropertyOfBaseOf(parameter);
          }
      }
      

      【讨论】:

        【解决方案4】:

        我认为你应该问问自己是否有更好的方法来做你想做的事。您希望 PropertyOfBase 在 MyType.MyMethod() 的上下文中充当公共,但在所有其他情况下都受到保护。为什么?

        【讨论】:

          【解决方案5】:

          你不能这样做是有充分理由的。假设有人写道:

          class Other : MyBase { }
          
          new MyType().MyMethod(new Other());
          

          如果语言允许您的要求,您可以通过修改 PropertyOfBase 的值来违反 Other 的假定不变量。

          【讨论】:

            【解决方案6】:

            不,你不能这样做。

            您只能访问访问类型(或从它派生)的对象的受保护成员。在这里,我们不知道参数是 MyType 类型还是 SomeOtherCompletelyDifferentType。

            编辑:C# 3.0 规范的相关位是第 3.5.3 节:

            当一个受保护的实例成员是 在程序文本之外访问 声明它的类,以及 当一个受保护的内部实例 成员在程序外被访问 它所在的程序的文本 声明,访问必须发生 在一个类声明中 派生自它所在的类 宣布。此外,访问是 需要通过一个发生 该派生类类型的实例或 从它构造的类类型。这 限制阻止一个派生类 从访问受保护的成员 其他派生类,即使当 成员继承自同一个 基类。

            【讨论】:

            • 我们不知道它是 MyType 还是 SomeOtherCompletelyDifferentType 但我们知道它是 MyBase 并且我们知道 MyBase 有一个名为 PropertyOfBase 的属性,所以它对我来说仍然有意义。
            • 规范不同意 :) 这是受保护访问的定义含义。
            • 嗯,但它说的是“当成员继承自同一个基类时”,而不是“当成员相同时”。我仍然不完全满意:)
            • 没有“成员相同”的概念。这意味着“即使您试图从 Derived1 的实例中获取 Derived2 实例中的成员 Base.X,其中 Derived1 和 Derived2 都从 Base 派生。”
            【解决方案7】:

            受保护的属性只能被派生类的实例访问,不能被派生类的实例访问。

            这是有区别的,它确实有意义,受保护的成员不应将其值放弃给任何其他实例,即使是从同一类型派生的实例。

            (已编辑,让自己有点不知所措!)

            【讨论】:

            • 但是如果参数是MyType,这个实例可以访问它,这显然是一个“其他”实例。
            最近更新 更多