2008-12-05 20 views
11
class MyBase 
{ 
    protected object PropertyOfBase { get; set; } 
} 

class MyType : MyBase 
{ 
    void MyMethod(MyBase parameter) 
    { 
     // I am looking for: 
     object p = parameter.PropertyOfBase; // error CS1540: Cannot access protected member 'MyBase.PropertyOfBase' via a qualifier of type 'MyBase'; the qualifier must be of type 'MyType' (or derived from it) 
    } 
} 

¿Hay alguna forma de obtener una propiedad protegida de un parámetro de un tipo que se extiende sin reflejarse? Dado que la clase que se extiende se sabe de la propiedad a través de su tipo base, tendría sentido si es posible.¿Hay alguna manera de llegar a un miembro `protected` de otro objeto desde un tipo derivado?

+0

Hazlo público en lugar de protegido. – dalle

+0

¿Qué sucede si no quiero que sea accesible desde otras clases, que no tienen nada que ver con PropertyOfBase? –

+0

¿Lo hace interno? – dalle

Respuesta

11

No, no puedes hacer esto.

Solo tiene permiso para acceder a miembros protegidos de objetos del tipo de acceso (o derivados de él). Aquí, no sabemos si el parámetro es de tipo MyType o SomeOtherCompletelyDifferentType.

EDIT: El bit correspondiente de la especificación de C# 3.0 es la sección 3.5.3:

Cuando un miembro de instancia protegido se accede fuera del texto de programa de la clase en la que se declara, y cuando se accede a un miembro de instancia interna protegida fuera del texto del programa del programa en el que es declarada, el acceso debe tener lugar dentro de un declaración de la clase que deriva de la clase en la que es declarado. Además, el acceso es requerido para tener lugar a través de una instancia de ese tipo de clase derivada o un tipo de clase construido a partir de él. Esta restricción impide que una clase derivada acceda a miembros protegidos de otras clases derivadas, incluso cuando los miembros se heredan de la misma clase base .

+1

No sabemos si es MyType o SomeOtherCompletelyDifferentType, pero sabemos que es MyBase y sabemos que MyBase tiene una propiedad llamada PropertyOfBase, por lo que todavía tiene sentido para mí. –

+0

La especificación no está de acuerdo :) Este es el significado definido de acceso protegido. –

+0

Guau, es imposible por diseño. Gracias. –

1

A una propiedad protegida solo se puede acceder a una instancia de una clase derivada, no a instancias de clases derivadas.

Existe una diferencia y tiene sentido, los miembros protegidos no deben renunciar a su valor a ninguna otra instancia, incluso una instancia derivada del mismo tipo.

(Editado, metí un poco la lengua atada!)

+0

Pero si el parámetro era de MyType, sería accesible para esta instancia y esta es claramente una "otra" instancia. –

+0

Bien dicho, ¡no sabía que funcionaría! – user42467

5

Hay una buena razón por la que no puede hacer esto. Supongamos que alguien escribe:

class Other : MyBase { } 

new MyType().MyMethod(new Other()); 

Si el idioma permitió lo que estás pidiendo, podría violar los invariantes asumidos de Other modificando el valor de PropertyOfBase.

2

Creo que debe preguntarse si hay una mejor manera de hacer lo que quiere hacer. Desea que PropertyOfBase actúe como público en el contexto de MyType.MyMethod(), pero para estar protegido en todas las demás situaciones. ¿Por qué?

14

La última vez que me enfrentaba a un problema similar, que utiliza la solución de la adición de un método estático protegido a la base:

class MyBase 
{ 
    protected object PropertyOfBase { get; set; } 

    protected static object GetPropertyOfBaseOf(MyBase obj) 
    { 
     return obj.PropertyOfBase; 
    } 
} 

class MyType : MyBase 
{ 
    void MyMethod(MyBase parameter) 
    { 
     object p = GetPropertyOfBaseOf(parameter); 
    } 
} 
0

Como usted está heredando de MyBase, puede acceder a todos los campos/propiedades/métodos de marcó como "protegido" utilizando la palabra clave "base".

public class MyBase 
{ 
    protected object PropertyOfBase { get; set; } 
} 

public class MyType : MyBase 
{ 
    void MyMethod() 
    { 
     object p = base.PropertyOfBase; 
    } 
} 
0

También puede declarar MyType como una clase anidada de MyBase (en lugar de heredar), de esta manera se puede acceder a miembros privados/protegido cuando se envía el MyBase clase como un parámetro

public class MyBase 
{ 
    protected object PropertyOfBase { get; set; } 

    public class MyType 
    { 
     public void MyMethod(MyBase parameter) 
     { 
      object p = parameter.PropertyOfBase; 
     } 
    } 
} 

Para cree una instancia de MyType simplemente use

var t = new MyBase.MyType(); 
t.MyMethod(new MyBase()); 
Cuestiones relacionadas