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 a protected 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 accessing protected 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; } }

其他提示

That's a curious way of making the derived constructor. Why not:

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

    public void Test()
    {
        //here, it's perfectly ok to access the protected Name.
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top