使子类中的成员只读

时间:2015-08-14 13:00:42

标签: c# inheritance

假设我有一个成员int number的A类,它有一个getter和一个setter。

然后我创建一个A的子类并将其称为B.现在,在BI类中希望保留成员number,但是在这个类中我想强加number读取的限制 - 只要。我怎么能这样做?

2 个答案:

答案 0 :(得分:8)

对此的需求通常暗示您的设计不是最优的(因为它违反了Liskov替代原则)。因此,C#并不真正支持它。但是,以下是种类实现它的两种方法:

(1)隐藏后代中的属性并提供替换基类的getter的新属性。但这并没有真正保护属性,因为你可以只转换到基类:

class A
{
  public int Number { get; set; }
}

class B : A
{
  public new int Number
  {
    get { return base.Number; }
  }
}

B b = new B();
// b.Number = 42; // This does not work.
A a = b;
a.Number = 42;
Console.WriteLine(b.Number); // == 42. Oops.

(2)用异常抛出覆盖setter。但错误的用法现在导致运行时错误而不是编译器错误,这是不好的。考虑向基础添加bool CanSetNumber属性(.NET与Stream.CanSeekSeek类似。)

class A
{
  public virtual int Number { get; set; }
}

class B : A
{
  public override int Number
  {
    get { return base.Number; }
    set { throw new InvalidOperationException("B.Number is readonly!"); }
  }
}

B b = new B();
b.Number = 42; // BAM!

答案 1 :(得分:2)

我同意塞巴斯蒂安的回答。另一个需要考虑的选择是使用通用接口而不是直接继承

public interface IHasNumber 
{
    int Number { get; }
}

public class A : IHasNumber 
{ 
    public int Number { get; set; } 
}
public class B : IHasNumber 
{ 
    public int Number { get; } 
}

如果您想共享这些值,则必须将A封装在B中。

public class B : IHasNumber 
{ 
    public B(A data) { this.Data = data; }
    private A Data { get; private set; }
    public int Number { get { Data.Number; } } 
 }

用作

{
    var A = new A();
    A.Number = 100;   // ok
    var B = new B(A);
    B.Number = 200;   // error
    Console.WriteLine(B.Number);  // prints 100
}