I have a class like this:
public class Base
{
public Base(string name)
{
this.Name = name;
}
public string Name { get; set; }
public string PrettyName
{
get { return Prettify(Name); }
}
}
and I derive from it:
public class Derived : Base
{
public Derived(Base b) : base(b.Name) { }
}
The Name
property should not be accessed; the logical name should be accessed only by PrettyName
. So I thought I'd make the property like this:
public string Name { protected get; set; }
But I'm getting this:
Cannot access protected member 'Name' via a qualifier of type 'Base'; the qualifier must be of type 'Derived' (or derived from it)
Why is that? The getter should be exposed to the base class and all its child classes. Am I getting something wrong here?
The getter should be exposed to the base class and all its child classes.
No, not quite. This isn't a matter of automatically implemented properties - it's a matter of what protected
means.
Access to a protected member within a subclass has to be through an instance of that subclass (or a further subclass). You can't use Base.Name
for an arbitrary Base
in Derived
.
From section 3.5.3 of the C# spec:
When a
protected
instance member is accessed outside the program text of the class in which it is declared, and when aprotected internal
instance member is accessed outside the program text of the program in which it is declared, the access must take place within a class declaration that derives from the class in which it is declared. Furthermore, the access is required to take place through an instance of that derived class type or a class type constructed from it. This restriction prevents one derived class from accessingprotected
members of other derived classes, even when the members are inherited from the same base class.
A simple solution would be to overload the constructor in Base
:
protected Base(Base b) : this(b.Name)
{
}
then in Derived
:
public Derived(Base b) : base(b) { }
At that point, you can make the Name
setter private, too - or better yet, make it fully read-only:
private readonly string name;
public string Name { get { return name; } }