为什么派生类无法从基类访问受保护的getter?

时间:2013-11-28 13:29:26

标签: c# properties encapsulation setter getter

我有一个这样的课程:

public class Base
{
    public Base(string name)
    {
        this.Name = name;
    }

    public string Name { get; set; }
    public string PrettyName
    {
        get { return Prettify(Name); }
    }
}

我从中得出:

public class Derived : Base
{
    public Derived(Base b) : base(b.Name) { }
}

不应访问Name属性;逻辑名称只能由PrettyName访问。所以我以为我会把这个属性做成这样的:

    public string Name { protected get; set; }

但我得到了这个:

Cannot access protected member 'Name' via a qualifier of type 'Base'; the qualifier must be of type 'Derived' (or derived from it)  

为什么? getter应该暴露给基类及其所有子类。我在这里弄错了吗?

2 个答案:

答案 0 :(得分:5)

  

getter应该暴露给基类及其所有子类。

不,不完全。这不是自动实现的属性问题 - 这是protected的意思。

访问子类中的受保护成员必须通过该子类(或另一个子类)的实例。您无法在Base.Name中使用Base作为任意 Derived

来自C#规范的第3.5.3节:

  

当在声明它的类的程序文本之外访问protected实例成员时,以及在程序的程序文本之外访问protected internal实例成员时声明,访问必须在一个类声明中发生,该声明派生自声明它的类。此外,需要通过该派生类类型的实例或从其构造的类类型进行访问。此限制可防止一个派生类访问其他派生类的protected成员,即使成员是从同一基类继承的。

一个简单的解决方案是重载Base中的构造函数:

protected Base(Base b) : this(b.Name)
{
}

然后在Derived

public Derived(Base b) : base(b) { }

此时,您可以将Name setter设为私有 - 或者更好,将其设置为完全只读:

private readonly string name;
public string Name { get { return name; } }

答案 1 :(得分:0)

这是制作派生构造函数的一种奇怪方式。为什么不:

public class Derived : Base
{
    public Derived(string name) : base(name)
    { }

    public void Test()
    {
        //here, it's perfectly ok to access the protected Name.
    }
}