【问题标题】:Why doesn't my use of "protected" work? [duplicate]为什么我对“受保护”的使用不起作用? [复制]
【发布时间】:2011-08-04 00:36:53
【问题描述】:

我读到可以从派生类访问受保护的成员,但以下不起作用。

class A
{
    protected int Test;
}
class B:A
{
    A instanceOfA= new A()

    public B()
    {
        instanceOfA.Test //Not possible
    }
}

【问题讨论】:

标签: c# protected


【解决方案1】:

我读到可以从派生类访问受保护的成员。为什么我对“受保护”的使用不起作用?

这是非法的,因为您没有保证您正在访问“B”实例的数据。考虑这种类似的情况:

abstract class BankAccount
{
    protected int accountNumber;
}
class SwissBankAccount : BankAccount
{
}
--- in another assembly, evil-doers write ---
class EvilBankAccount : BankAccount
{
    void DoEvil()
    {
        BankAccount b = GetASwissBankAccount();
        int number = b.accountNumber;
    }
}

EvilBankAccount 不继承自 SwissBankAccount,因此 SwissBankAccount 的受保护成员不允许在 EvilBankAccount 内部使用。您可以访问“父母”的受保护成员,但不能访问“兄弟姐妹”! EvilBankAccount 只能访问EvilBankAccount(或从 EvilBankAccount 派生的类型)的受保护成员。 SwissBankAccount 的受保护成员不受限制。

规则是通过访问受保护实例成员的“接收者”表达式的类型必须至少与类型声明包含会员访问。有关规则的准确措辞和一些说明性示例,请参阅 C# 4.0 规范的第 3.5.3 节。

顺便说一句,C++ 也有这个规则。

这条规则经常被误解。有关此规则和受保护访问的其他一些后果的更深入分析,请参阅我关于该主题的文章。我在这个主题上写的最贴切的文章是this onethis one。我写了很多关于相关主题here 的文章(尽管其中一些文章偏离了受保护访问本身的主题,而转向了如何使用受保护访问来构建具有父引用的数据模型的主题。)

【讨论】:

  • @FreeAsInBeer:好吧,您有权获得您的专家意见。我不认为你的回答实际上回答了这个问题。而不是回答“为什么这种使用受保护的方法不起作用?”正如我所做的那样,您反而选择说“您做错了”,而没有解释 C# 的什么规则导致了错误。我经常收到这个问题;这是语言设计和类型安全的一个微妙点。
  • @FreeAsInBeer:你知道埃里克·利珀特是谁,对吧??
  • @marc_s:虽然我同意你的观点——当我第一次回答这样的关于编程语言设计的问题时,一个三年级的人正在试图教育我,这真是太有趣了——让我们请记住,StackOverflow 是一个基于社区的系统。社区根据其感知的正确性和有用性来判断答案,而不是根据给出答案的人的所谓凭据。如果比尔少爷认为我给出了一个垃圾答案,他当然有权发表他的意见,我们不应该否认他。
  • @Eric Lippert:当然——很棒的社区也是如此!我只是猜测你的职位(作为微软 C# 设计团队的成员),你可能确实大多数 其他程序员 :-)
  • @FreeAsInBeer:我真诚的建议是深呼吸,不要过于情绪化。这是一个社区站点,我们都在这里通过互相帮助解决技术问题来互相帮助和学习。良好的编程很难,语言很复杂,讽刺对任何人都没有帮助。
【解决方案2】:

如果继承A,则无需创建A 的实例。

class A
{
   protected int Test;
}
class B:A
{
   public B()
   {
     this.Test = 666;
   }
}

【讨论】:

    【解决方案3】:

    子类可以访问它们自己的被标记为protected的继承成员。

    class A
    {
       protected int Test;
    }
    
    class B : A
    {
       public B()
       {
         this.Test = 42; // Possible
       }
    }
    

    【讨论】:

      【解决方案4】:

      您可以通过同一个类访问它,而不是作为基类的公共成员。

      class A 
      { 
          protected int Test; 
      } 
      
      class B:A 
      { 
          void TestMethod()
          {
               this.Test = 3; // Possible
          }
      }
      

      在 C# 中检查 protected 访问修饰符。

      【讨论】:

        【解决方案5】:

        由于B 已经从A 继承,您不需要A 的单独实例。

           public B()
           {
             this.Test = 1; //possible
           }
        

        【讨论】:

          【解决方案6】:

          您可以在B 类本身中访问Test int。但是,您不能访问实例的属性。 A 不知道它是 B 的孩子,因此不会授予访问其属性的权限。

          class A
          {
              protected int Test;
          }
          class B : A
          {
              public B()
              {
                 Test = 3; //possible
                 base.Test = 3;  //explicitly calling base member, but not necessary in this case
              }
          }
          

          【讨论】:

            【解决方案7】:

            您的代码设置不正确。 B 类不应有 A 类的实例。相反,B 类本身继承了A 类的受保护变量。

            您的代码应该看起来更像:

            class A
            {
               protected int Test;
            }
            class B:A
            {
               public B()
               {
                   int someInt = this.Test;
               }
            }
            

            【讨论】:

            • +1 只是添加 - 您可以从派生类的实例访问受保护的基类成员 - 更多详细信息请参见 msdn.microsoft.com/en-us/library/bcd5672a%28v=VS.71%29.aspx
            • 问题是我希望我可以访问基类实例的受保护成员,所以我只是尝试在派生类中创建基类的实例
            • @SolutionYogi - B 也继承自 OP 代码中的 A。
            • @FreeAsInBeer:真的,认真的家伙,深呼吸。你对“真相”和“正义”大发雷霆,但我们都不会最终来到海牙(我希望如此)。一个简单的事实是,这个答案不是很好。它甚至没有开始解决所提出的实际问题。请记住,“为什么”的问题应该用“因为”的答案来回答;您给出了适合“我该怎么做”问题的“如何做”答案。把它当作学习的机会;下次,请仔细阅读问题并了解真正提出的问题。
            • @Eric,@Greg:谢谢。我感谢建设性的批评,并希望提供更明确的答案,以便将来更好地解决这个问题。
            猜你喜欢
            • 2015-07-05
            • 2015-01-12
            • 2011-03-14
            • 2015-06-14
            • 2018-09-26
            • 2019-08-29
            • 1970-01-01
            • 1970-01-01
            • 2017-06-09
            相关资源
            最近更新 更多