2013-11-28 72 views
2

我有这样一个类:为什么派生类无法从基类访问受保护的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应该暴露给基类和它的所有子类。我在这里弄错了什么?

回答

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二传手私人,太 - 或更好,使其完全只读:

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

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

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

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

因为示例代码是简化的,我试图用真正的代码实现的是将'b'的所有属性(不止是名称)复制到新对象。 –

相关问题