2010-07-16 23 views
10

Estoy usando .NET 2.0, por lo que no tengo acceso a las propiedades automáticas. Por lo que debe recurrir a la siguiente forma de codificar las variables privadas y propiedades públicas¿Bloquea el acceso a las variables de miembros privados? ¿Forzar el uso de propiedades públicas?

private string m_hello = null; 

public string Hello 
{ 
    get{return m_hello;} 
    set{m_hello = value;} 
} 

Para los métodos de la clase que contiene los miembros privados/públicos por encima, hay alguna forma de restringir el acceso a la variable privada? No me gusta que pueda usar m_hello o Hello.

Gracias.

+10

Una cosa a tener en cuenta: incluso si está apuntando a .NET 2.0, si está usando C# 3 para hacerlo, todavía puede usar propiedades automáticas. No requieren ningún soporte de marco. –

+0

@Jon: probablemente sea información suficientemente importante para justificar una respuesta en lugar de un comentario. – tvanfosson

+0

@tvanfosson - ¡Estoy de acuerdo, no tenía ni idea de eso! – adamwtiko

Respuesta

5

No, no hay una manera de hacer eso, aparte de simplemente seguir su propia convención y hacer esto. Hola, si realmente necesita pasar por su propiedad pública.

No veo por qué necesitarías o querría hacer esto tampoco, ya que como es tu clase interna, tú eres el que tiene el control del código y puedes definir qué/cómo se usa, por lo que hay no debería ser un problema.

+0

Woah! Lo siento @Mitchel: accidentalmente edité la publicación incorrecta. Lo siento por eso. –

+0

@Marc - ¿Te atrapó la encantadora función de ordenar al azar? Tuve que suceder más de una vez, y automáticamente asumí que mi pregunta estaba en la misma posición después de una edición (o presentación) y presioné ciegamente el botón de edición. No ayuda cuando la respuesta en esa posición comienza con prácticamente el mismo texto. – tvanfosson

2

No, básicamente. Bueno, usted podría hacer algo con las advertencias del compilador a través de [Obsolete] y #pragma, pero eso sería excesivo.

Se podría probablemente hacerlo con las herramientas, pero con el tiempo que tienen que confiar en la gente para no hacer cosas estúpidas. Después de todo, ¿tienes reglas especiales sobre: ​​

while(true) { } 

o simplemente lo pones en "no seas estúpido"? ; p

+1

'while (true)' plus 'break' dentro del cuerpo del bucle es una construcción de programación perfectamente válida. Hay cosas mucho peores que eso. –

+1

@ToxicAvenger - pero * sin * el 'break'? –

4

No. Cualquier método dentro de la clase tendrá acceso a ambos.

Su equipo debe estandarizar el uso (propiedad o variable privada).

Una vez que decida cuál usar, podría intentar usar una regla FxCop personalizada para aplicar el estándar.

1

Solo debe acceder a la propiedad a través de la propiedad pública Hello. Esta es la razón de este patrón. Si agrega alguna funcionalidad al get o al set, si está accediendo a la instancia privada, introducirá errores en su código. Pero el error es NO, no puedes evitar que alguien llame al Privado cuando están dentro de tu clase cambiando tu código.

+0

Podría decirse que puede funcionar en ambos sentidos: es posible que desee hacer referencia directamente al campo de respaldo para que no se vea afectado por ninguna adición a la propiedad pública. Sin embargo, sería una buena idea ser consecuente con esto y, posiblemente, una buena idea identificar claramente las variables de respaldo, ya que está claro que se está pasando por alto una propiedad. Por ejemplo, puedes sufijarlos con '_Prop' o algo así. –

+0

Prefiero consistencia y solo quería señalar el motivo del patrón. Siempre hay una razón para que cada uno se solucione, no es una buena práctica. – CkH

1

Personalmente, no veo nada de malo en acceder al miembro privado dentro de la clase. De hecho, eso es lo que normalmente hago (a menos que exista una lógica dentro de la propiedad getter/setter que siempre quiero aprovechar).

Simplemente tiene sentido para mí: el código dentro de la clase constituye implementación de esa clase; ¿Por qué ocultar una implementación de sí mismo?

Aquí hay un ejemplo de lo que quiero decir. Supongamos que tengo algún miembro, m_denominator, y quiero que nunca sea cero:

private int m_denominator = 1; 
public int Denominator 
{ 
    get { return m_denominator; } 
    set 
    { 
     if (value == 0) 
      throw new ArgumentException("Denominator must not be zero."); 
     m_denominator = value; 
    } 
} 

podría decir a mí mismo: "OK, donde quiera que establece este valor dentro de esta clase, que debe utilizar Denominator para asegurarse de que No lo estoy poniendo a cero ". Pero estoy completamente en control de lo que estoy configurando Denominator - ¡Estoy dentro de la clase! En este escenario, el objetivo de la lógica en la propiedad Denominator es proteger la clase de los valores no válidos establecidos por el código del cliente. No hay excusa para establecer su estado interno a algún valor no válido dentro de la implementación de una clase.

Por supuesto, esta no es una regla absoluta. Seguramente hay momentos en que usar la propiedad por su lógica dentro de una clase puede ser una elección sensata como medida de protección; Realmente, solo estoy argumentando que es no está mal para acceder a miembros privados dentro de una clase.

+2

Entonces, ¿qué sucede cuando vuelves al código en 6 meses para agregar una lógica importante al establecedor de propiedades? Todo el código interno de su clase ahora pasará por alto las nuevas implementaciones. –

+3

Prefiero el uso predeterminado de la propiedad, precisamente porque no quiero hacer un seguimiento de los lugares donde la propiedad hace algo especial. Por lo general, el optimizador se ocupará de optimizar la llamada del método, al menos para un acceso simple. Solo usaré la propiedad cuando sepa que la propiedad hace algo "especial" y quiero evitar eso para algún propósito en particular. – tvanfosson

+2

@Dr Herbie: Pero en mi experiencia, es muy probable que agregue lógica a la propiedad, pero * no * quiere que se ejecute esa lógica en cada acceso que suceda dentro de la clase, solo en accesos desde código externo. Definitivamente, he trabajado con desarrolladores que agregaron lógica a sus propiedades y, de repente, descubrieron que parte de su código se ejecutaba mucho más a menudo de lo que pretendían. Es una decisión, obviamente; Solo estoy señalando que hay una diferencia entre esconder tu implementación del mundo exterior y esconderla ... de sí misma. –

6

Esto se puede hacer a través de la herencia:

abstract class A // A is not instantiatable due to being abstract 
{ 
    private string m_hello = null; 

    public string Hello 
    { 
     get{return m_hello;} 
     set{m_hello = value;} 
    } 
} 

class B : A 
{ 
    // B now cannot access the private variable, use B in your code instead of A 
} 
+3

Sí, pero ... puaj. – tvanfosson

+3

Nunca dije que fuera bueno. Solo que se podría hacer. –

1

Si usted se encuentra el deseo de ocultar los detalles del mismo, que puede ser un olor código que su clase tiene demasiadas responsabilidades. Considere la posibilidad de extraer una de las responsabilidades en una nueva clase.

+0

A veces no es "usted mismo", pero hay otros miembros de su equipo que no pueden seguir las reglas. Lo sé, en teoría, todo tiene una solución simple, pero la vida es dura ... – bpiec

+0

@JoeWhite: ese es un punto de vista interesante. Sin embargo, fragmentar las clases hasta un nivel donde cada una tiene una responsabilidad casi trivial suena bien en teoría, pero en la práctica puede ser una pesadilla para comprender por sí mismo. – oliver

8

Como otros han sugerido que esta debe ser una respuesta ...

Puede seguir utilizando las propiedades automáticas en C# 3 cuando la orientación de .NET 2.0, junto con quite a few other C# 3 features. A diferencia de los árboles de expresiones (por ejemplo), las propiedades automáticas no necesitan nada especial del CLR o el marco, más allá del atributo [CompilerGenerated] (que se introdujo en .NET 2.0).

Si está utilizando VS2008 o VS2010, entonces valdría la pena utilizar una propiedad automática.

Por lo que vale la pena, me gustaría esta habilidad también. Me gustaría ser capaz de variables de ámbito dentro de una propiedad:

public string Name 
{ 
    private string name; 
    get { return name; } 
    set { name = value; } 
} 

Veo esto un poco como hacer una variable privada de sólo lectura - no hace ninguna diferencia a los clientes, sino que ayuda a hacer cumplir la corrección dentro del código de la clase sí mismo.

+2

+1 - Acepto completamente la variable de propiedad de ámbito privado. Realmente me gustaría tener la capacidad de tener código arbitrario en los métodos de propiedad ** y ** limitar el acceso al campo de respaldo a la propiedad solo para que no evite accidentalmente las "reglas" en el código getter/setter. – tvanfosson

+1

Tangencialmente relacionado, me gustaría tener propiedades automáticas inmutables también (configurable mediante la sintaxis de constructor o inicializador) y luego solo gettable desde allí. Respaldado por un campo 'readonly' generado por el compilador. –

Cuestiones relacionadas