【问题标题】:Can I override a property in c#? How?我可以覆盖 c# 中的属性吗?如何?
【发布时间】:2025-03-31 01:35:01
【问题描述】:

我有这个基类:

abstract class Base
{
  public int x
  {
    get { throw new NotImplementedException(); }
  }
}

还有以下后代:

class Derived : Base
{
  public int x
  {
    get { //Actual Implementaion }
  }
}

当我编译时,我收到这个警告,说 Derived 类对 x 的定义将隐藏 Base 的版本。是否可以在 c# 中覆盖类似方法的属性?

【问题讨论】:

    标签: c# inheritance properties polymorphism overriding


    【解决方案1】:

    你需要使用virtual关键字

    abstract class Base
    {
      // use virtual keyword
      public virtual int x
      {
        get { throw new NotImplementedException(); }
      }
    }
    

    或定义一个抽象属性:

    abstract class Base
    {
      // use abstract keyword
      public abstract int x { get; }
    }
    

    在孩子中使用override关键字:

    abstract class Derived : Base
    {
      // use override keyword
      public override int x { get { ... } }
    }
    

    如果你不打算覆盖,你可以在方法上使用new关键字来隐藏父级的定义。

    abstract class Derived : Base
    {
      // use new keyword
      public new int x { get { ... } }
    }
    

    【讨论】:

      【解决方案2】:

      将基属性抽象化并在派生类中覆盖或使用 new 关键字。

      abstract class Base
      {
        public abstract int x { get; }
      }
      
      class Derived : Base
      {
        public override int x
        {
          get { //Actual Implementaion }
        }
      }
      

      或者

      abstract class Base
      {
        public int x { get; }
      }
      
      class Derived : Base
      {
        public new int x
        {
          get { //Actual Implementaion }
        }
      }
      

      【讨论】:

      • 或者你可以在基类上使用 virtual,就像 Jeffrey Zhao 提到的那样。
      【解决方案3】:

      如下图改变属性签名:

      基类

      public virtual int x 
      { get { /* throw here*/ } }
      

      派生类

      public override int x 
      { get { /*overriden logic*/ } }
      

      如果您不需要基类中的任何实现,只需使用抽象属性即可。

      基地:

      public abstract int x { get; }
      

      派生:

      public override int x { ... }
      

      我建议您使用 abstract 属性而不是在 getter 中使用 NotImplemented 异常,abstact 修饰符将强制所有派生类实现此属性,因此您最终将获得编译时安全的解决方案。

      【讨论】:

        【解决方案4】:
        abstract class Base 
        { 
          // use abstract keyword 
          public virtual int x 
          { 
            get { throw new NotImplementedException(); } 
          } 
        } 
        

        【讨论】:

          【解决方案5】:
          abstract class Base
          {
          
            public virtual int x
            {
              get { throw new NotImplementedException(); }
            }
          }
          

          abstract class Base
          {
            // use abstract keyword
            public abstract int x
            {
              get;
            }
          }
          

          在这两种情况下,您都必须在派生类中编写

          public override int x
            {
              get { your code here... }
            }
          

          两者之间的区别在于,使用 abstract 你强制派生类实现某些东西,而使用 virtaul 你可以提供派生者可以按原样使用或更改的默认行为。

          【讨论】: