2015-11-26 2 views
0

У меня есть базовый класс O и два производных класса: A : O и B : 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:

Защищенное ключевое слово - модификатор доступа к членству. Защищенный член доступен в своем классе и экземплярах производного класса.

Но хотя оба A и B были производные классы от O, они не могли использовать друг друга базовых защищенных членов.

Любые предложения обойти это в моем случае? (Вместо того, чтобы событие public)

+0

Почему бы вам не сделать это мероприятие общедоступным? Вы хотите, чтобы только определенные типы могли регистрироваться? –

+0

'B' не наследуется от' A', поэтому вы не можете получить доступ к этому событию. Они имеют одну и ту же базу, но не наследуют. –

+0

@YuvalItzchakov Да, я хочу, чтобы только зарегистрированные классы 'O' регистрировались. –

ответ

1

Если O, A и B находятся в одной и той же сборке, вы можете использовать internal, если вы не хотите, чтобы это публично. В противном случае вы ограничены public доступом в этом случае.

При попытке доступа к базовому классу таким образом вы получаете доступ к нему только через API public, а не через 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, как говорится в цитате:

Защищенная ключевое слово является модификатор доступа члена.Защищенный член доступен в своем классе и производного класса экземпляры

(курсив мой).

1

Но хотя оба A и B были производный классы от O, они не могли использовать друг друга базовых защищенных членов.

Этого можно ожидать.

Защищенный член доступен в пределах его класса и экземпляров производного класса.

A происходит от O, не B так что нет никакого способа, которым он может видеть защищенные члены B (и наоборот).

Если вы хотите, чтобы эти классы могли видеть друг друга/события/и т. Д., Вам необходимо сделать их общедоступными.

0

У вас есть экземпляр A как поле класса B. Защищенный используется для доступа внутри производного класса, но не снаружи. Таким образом, существует только одно решение - использовать общественность.

+1

Существует еще одно решение: 'internal'. –

+0

Конечно, просто забудьте об этом – Anton

+0

Но это также сделает это событие видимым для других классов в сборке – Anton

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; 
    } 
} 
Смежные вопросы