如何在派生类中添加属性设置器? (C#)

16
我有一个需求,其中有许多类都派生自同一个基类。基类包含了派生自同一基类的子类列表。
所有类都需要能够获取特定值,这些值可以从类本身或其父类中获取,具体取决于派生类是什么。
我考虑使用方法而不是属性,但我还希望将这些值提供给.NET报表组件,该组件直接访问报表引擎中公开的公共属性,因此这排除了使用方法的可能性。
我的问题是,在没有在BaseClass中公开setter的情况下,如何在DerivedClass中实现setter的最佳实践方法。
public class BaseClass
{
  private BaseClass _Parent;
  public virtual decimal Result
  {
    get { return ((_Parent != null) ? _Parent.Result : -1); } 
  }
}

public class DerivedClass : BaseClass
{
  private decimal _Result;
  public override decimal Result
  {
      get { return _Result; }
      // I can't use a setter here because there is no set method in the base class so this throws a build error
      //set { _Result = value;  }
  }
}

由于我无法更改DerivedClass中的访问修饰符,因此无法在BaseClass中添加受保护的setter(如下所示)。

public class BaseClass
{
  private BaseClass _Parent;
  public virtual decimal Result {
    get { return ((_Parent != null) ? _Parent.Result : -1); } 
    protected set { }
  }
}

public class DerivedClass : BaseClass
{
  private decimal _Result;
  public override decimal Result
  {
    get { return _Result; }
    // This setter throws a build error because of a change of access modifiers.
    //set { _Result = value; }
  }
}

我不想在BaseClass中添加一个带有setter的成员变量,因为我不希望从BaseClass或其他继承自基类的类中设置属性的能力。

public class BaseClass
{
  private BaseClass _Parent;
  protected Decimal _Result; // This could result in a lot of unnecessary members in BaseClass.

  public virtual decimal Result {
    get { return _Result; } 
    // Empty setter ahead :) This does nothing.
    // I could also throw an exception here but then issues would not be found until runtime
    // and could cause confusion in the future with new developers etc.
    set { }
  }
}

public class DerivedClass : BaseClass
{
  public override decimal Result
  {
    get { return base.Result; }
    set { base._Result = value; }
  }
}

其他建议?

1
请参见https://dev59.com/Kmw15IYBdhLWcg3wO5MH(不完全是重复)。 - Jeroen Mostert
3个回答

5
如果你可以在BaseClass中添加一个受保护的setter,那么你就可以在DerivedClass中使用new关键字:
public class BaseClass  // ReadOnlyClass
{
    public int Value { get; protected set; }
}

public class DerivedClass : BaseClass
{
    public new int Value
    {
        get => base.Value;
        set => base.Value = value;
    }
}

4
您可以使用“new”关键字,但这将替换属性,使用覆盖不可能实现您想要的。
public class BaseClass
{
    private BaseClass _Parent;
    public virtual decimal Result
    {
        get { return ((_Parent != null) ? _Parent.Result : -1); }
    }
}

public class DerivedClass : BaseClass
{
    private decimal _Result;
    public new decimal Result
    {
        get { return _Result; }
        set { _Result = value;  }
    }
}

0
我最终改变了处理方式,将设置留在基类中,但是与其让基类getter/setter什么也不做,我抛出了一个NotImplemented / NotSupported异常。
public class BaseClass
{
  private BaseClass _Parent;
  public virtual decimal Result
  {
     get
     {
      if (Parent == null)
        throw new NotImplementedException("Result property not valid");

      return Parent.Result;
    }
    set
    {
      throw new NotSupportedException("Result property cannot be set here");
    }
  }
}

public class DerivedClass : BaseClass
{
  private decimal _Result;
  public override decimal Result
  {
    get { return _Result; }
    set { _Result = value;  }
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接