受保护的成员在派生类中无法访问?

时间:2015-11-26 14:21:11

标签: c# oop event-handling protected access-modifiers

我有一个基类O,还有两个派生类:A : OB : O,如下所示:

public abstract class O
{
    public O(string val)
    {
        this.Value = val;
    }

    private string value;
    public string Value
    {
        get { return this.value; }
        set
        {
            this.value = value;
            RaiseValueChanged();
        }
    }

    protected delegate void ValueChangedEventHandler();
    protected event ValueChangedEventHandler ValueChanged;
    protected void RaiseValueChanged()
    { if (ValueChanged != null) ValueChanged(); }
}

public sealed class A : O
{
    public A(string val)
        : base(val) { }
}

public sealed class B : O
{
    public B(string val, A instance)
        : base(val)
    {
        instanceA = instance;
    }

    private A instanceA;
    public A InstanceA
    {
        get { return instanceA; }
        set
        {
            instanceA = value;
        }
    }

    public void MyMethod()
    {
        //Some stuff..
    }
}

我想在B.MyMethod();被提出时致电B.instanceA.ValueChanged,但当我发现我不能这样做时,我感到很惊讶:

public sealed class B : O
{
    public B(string val, A instance)
        : base(val)
    {
        instanceA = instance;
        //instanceA.ValueChanged += MyMethod;
    }

    private A instanceA;
    public A InstanceA
    {
        get { return instanceA; }
        set
        {
            //instanceA.ValueChanged -= MyMethod;
            instanceA = value;
            //instanceA.ValueChanged += MyMethod;
        }
    }

    public void MyMethod()
    {
        //Some stuff..
    }
}

根据MSDN

  

protected关键字是成员访问修饰符。受保护的成员   可以在其类和派生类实例中访问。

但是,虽然AB都是来自O的派生类,但他们无法使用彼此的基本受保护成员。

有什么建议可以解决这个问题吗? (而不是制作事件public

4 个答案:

答案 0 :(得分:1)

  

但是,虽然AB都是来自O的派生类,但他们无法使用彼此的基本受保护成员。

这是可以预期的。

  

受保护的成员可以在其类和派生类实例中访问。

A源自O,而不是B,因此无法看到B的受保护成员(反之亦然)。

如果您希望这些课程能够看到彼此的成员/活动/等,那么您需要将它们公之于众。

答案 1 :(得分:1)

如果OAB都在同一个程序集中,如果您不希望它被公开,则可以使用internal。否则,在这种情况下,您只能public访问。

当您尝试以这种方式访问​​基类成员时,您只能通过public API访问它,而不能通过protected访问它。您可以通过尝试以下方式自行查看:

public sealed class B : O
{
    public B(string val, O instance)
        : base(val)
    {
        instanceO = instance;
        instanceO.ValueChanged += MyMethod;
    }

    private O instanceO;
}

这仍然会出现编译错误。您可以访问ValueChanged中的B,但只能访问B的实例,如引号中所述:

  

protected关键字是成员访问修饰符。受保护的成员可在其类中以及派生类实例

中访问

(强调我的)。

答案 2 :(得分:0)

您将instanceA作为B类的字段.Protected用于在派生类内部访问,但不在外部访问。因此,只有一种解决方案 - 使用公共。

答案 3 :(得分:0)

公开并试试。

这将保证两件事。

首先,关闭事件处理程序附加操作的调用者是从O派生的类的成员(或静态)方法,

其次,作为事件处理程序传递的委托是从O派生的类的成员(或静态)方法。

public delegate void ValueChangedEventHandler();

private event ValueChangedEventHandler valueChanged;
public event ValueChangedEventHandler ValueChanged
{
    add
    {
        if (!typeof(O).IsAssignableFrom(value.Method.DeclaringType))
        {
            throw new ArgumentException();
        }
        if (!typeof(O).IsAssignableFrom(new StackTrace().GetFrame(1).GetMethod().DeclaringType))
        {
            throw new ArgumentException();
        }
        valueChanged += value;
    }
    remove
    {
        valueChanged -= value;
    }
}