¿Debería usar private en campos y métodos en C #?

8

Soy algo nuevo en C # y acabo de descubrir que: en C # todos los campos y métodos en una clase son privados por defecto. Lo que significa que esto:

class MyClass
{

string myString

}

es lo mismo que:

class MyClass
{

private string myString

}

Entonces, debido a que son los mismos, ¿debería usar la palabra clave private en los campos y métodos? Muchos ejemplos de código en línea usan la palabra clave private en su código, ¿por qué es eso?

user3210251
fuente
34
Bueno, para empezar, es obvio que tu intención era hacer que tu campo fuera privado, en lugar de olvidarte de incluir un especificador de alcance.
KChaloux
44
Me incomoda no usar private. Es menos disonancia cognitiva para mí si siempre puedo esperar ver el especificador de alcance como la primera parte de una declaración de identificador. Me toma menos tiempo leer "privado" que darme cuenta de que la primera palabra no es un especificador de alcance y, oh sí, eso significa que es una declaración de miembro privado. Escribir código también se trata de tener que leerlo más tarde.
Robert Harvey
3
@RobertHarvey También puede ser completamente subjetivo; Al codificar en C ++, siempre omití todo lo que era opcional, porque sentí que me distraía, hasta que me di cuenta de que otras personas que leen mi código pueden estar acostumbradas a convenciones de codificación más detalladas. Entonces es una cuestión de gustos (en un proyecto personal) y de convención (cuando se colabora).
marczellm
2
@gnat No estoy seguro de que esto sea un duplicado de esa pregunta. ¿Estás seguro de haber publicado el enlace correcto?
maple_shaft
44
@gnat Es difícil preguntar por qué uno declararía explícitamente la palabra clave privada en su código es una pregunta sobre el estilo de codificación. Esta pregunta es mucho más específica que eso. Siento que si bien una respuesta canónica podría cubrir una pregunta diferente, una pregunta más específica a veces puede merecer su propia respuesta.
maple_shaft

Respuestas:

38

Solo porque puede omitir saltos de línea e indentaciones y su compilador de C # todavía entenderá lo que quiere decirle, no es automáticamente una buena idea hacerlo.

using System; namespace HelloWorld{class 
Hello{static void Main(){Console.WriteLine
("Hello World!");}}}

es mucho menos legible para el lector humano que:

using System;
namespace HelloWorld
{
    class Hello 
    {
        static void Main() 
        {
            Console.WriteLine("Hello World!");
        }
    }
}

Y ese es todo el punto aquí: los programas están escritos para dos audiencias:

  • El compilador o intérprete.
  • Tú y otros programadores.

El último es el que necesita comprender y comprender rápidamente el significado de lo que está escrito. Debido a esto, hay algunas buenas prácticas que han surgido a lo largo de los años y son cuasi-normas más o menos comúnmente aceptadas. Una de ellas es poner palabras clave de alcance explícito, otro ejemplo es poner paréntesis adicionales alrededor de expresiones complejas, incluso en casos en los que no serían necesarios sintácticamente, como:

(2 + 5) & 4
JensG
fuente
2
+1 En particular para ese último punto. Aunque estrictamente hablando, los programadores deben conocer el orden de las operaciones para su idioma, siempre trato de agregar paréntesis adicionales siempre que sea posible porque en el pasado me encontré perdiendo varios segundos tratando de pensar qué operación viene primero y si una expresión evalúa o no como creo que lo hace. De vez en cuando la respuesta es "No, lo tengo mal" y esas ocasiones se puede evitar con el uso razonable de los soportes, sobre todo si tenemos en cuenta casos como 5 + 5 * 5es 30, no 50como algunos podrían esperar a primera vista.
Pharap
1
+1. Hay un pequeño problema mental para mí cuando no veo modificadores de visibilidad explícitos. Tengo que pensar por una fracción de segundo, "¿Es el público predeterminado o privado?" simplemente porque siempre uso los modificadores, y cuando alguien no lo hace, me desconcierta.
Greg Bair
66
Quieres decir **private** static void Main()? :)
Jesse C. Slicer
6

C # no es el único lenguaje de programación para .NET; otros idiomas pueden tener accesibilidad predeterminada diferente en varios contextos. La especificación privatedejará en claro a cualquiera que lea el código que dicha accesibilidad está destinada, mientras que omitir la especificación deja abierta la pregunta de si el miembro podría haber sido, por ejemplo, destinado a ser utilizable dentro del ensamblado [como sería el valor predeterminado en VB.NET] . Ser explícito puede ser especialmente útil si uno usa múltiples idiomas con diferentes reglas.

Con respecto a si se debe favorecer privateo protectedno en ausencia de un argumento particularmente convincente a favor del otro, la decisión debe basarse en si es más probable que exponer a un miembro haga posible que una clase derivada haga algo útil que de lo contrario no sería posible, o que evitaría que futuras versiones de una clase modifiquen sus estructuras internas de datos de una manera que sería más eficiente. Uno puede ver ejemplos de ambas situaciones en List<T>.

En algunos casos, si uno tiene una lista de agregados (por ejemplo, Pointestructuras), puede ser útil actualizar los elementos en el lugar. Si se List<T>expone su almacén de respaldo a clases derivadas, se podría definir fácilmente EditableList<T>un método con:

delegate void ActByRef<T1,T2>(ref T1 p1, ref T2 p2);

void ActOnItem<TParam>(int index, ref TParam param, ActByRef<TParam> proc)
{
  .. test index, then...
  proc(ref _arr[index], ref proc);
}

que luego se podría invocar usando algo como:

int adjustmentAmount = ...;
myList.ActOnItem(index, ref adjustmentAmount, 
  (ref Point pt, ref int dx) => pt.X += dx );

Tal método podría permitir actualizaciones eficientes incluso con tipos de estructura relativamente grandes [ya que no se requeriría copia]. El hecho de que List<T>no exponga sus componentes internos hace que sea imposible derivar una clase que pueda implementar dicho operador de manera eficiente.

Por otro lado, aunque hasta donde yo sé, Microsoft aún no ha explotado esta capacidad, tener la tienda de respaldo en privado permitiría que una versión futura de List<T>dividir la tienda de respaldo en partes que fueran menores de 85K cuando se usa la mayoría de los datos tipos, o más pequeños que 1000 artículos cuando se usa double. Tal división no sería posible si List<T>hubiera expuesto el almacén de respaldo a clases derivadas.

Super gato
fuente
Como los campos son por defecto privada no espero Salida común lenguaje intermedio del compilador de C # de int myFieldy private int myFieldpara ser diferente. Por lo tanto, no creo que no agregar privado lo deje abierto a la interpretación para otros lenguajes .NET.
Roy T.
@RoyT .: Mi punto era que si se usan varios idiomas, puede que no esté claro que un miembro con un especificador de acceso omitido tenía la intención de tener el acceso que hubiera sido el predeterminado en un idioma diferente.
supercat
ah entiendo ahora. Se refería tan explícitamente a otros lenguajes .NET que lo entendí como programas que no entienden, no personas.
Roy T.
1
@RoyT .: edité el primer párrafo; ¿Eso lo hace más claro?
supercat
2

Sí, debe usarlo private:) La palabra clave se usa porque es una práctica generalmente aceptada y elimina todas las dudas sobre el alcance previsto de un miembro de la clase.

La legibilidad es muy importante con el código, especialmente cuando se trabaja en equipo. Si desea ver más la legibilidad del código, un buen libro de referencia que puedo recomendar es The Elements of C # Style .

ocasionalDev
fuente
-4

Pregunta:

"¿Debería usar private en campos y métodos en C #?"

Respuesta rápida:

Sí, pero depende de la lógica de su código.

Respuesta extendida larga y aburrida:

Sugiero, siempre especifique la visibilidad para los miembros.

Creo que es un buen enfoque declarar miembros, por defecto, como "privados".

En el mundo real, uso "protegido" en su lugar.

Tarde o temprano, ese miembro oculto podría ser utilizado por una subclase.

A veces, una buena pregunta puede responderse mejor haciendo la pregunta opuesta.

La pregunta opuesta, a su pregunta, podría ser algo como:

"¿Debo usar siempre el modificador de acceso público en campos y métodos en C #"

En otros lenguajes de programación puede "promocionar" protegido al público, dependiendo de su diseño.

Utilizo muchas bibliotecas de jerarquía profunda de control (visual), donde se requieren algunos miembros (propiedades, métodos).

A veces, es mejor tenerlos públicos, a veces no.

umlcat
fuente
55
Usar protegido como su especificador de acceso puede ser malo. Potencialmente abre la superclase a la manipulación que podría no ser apropiada, ya que una subclase podría evitar las verificaciones de errores o las restricciones establecidas en la superclase. Incluso si ese no es el caso, aún contamina las subclases con variables adicionales dentro del alcance que son redundantes (por ejemplo, la variable protegida con un descriptor de acceso ahora proporciona dos formas de cambiarla en una subclase).
2
-1: no intenta abordar la pregunta.
mattnz
1
Público y protegido están en mi humilde opinión más cerca que privado y protegido. Son parte de la interfaz de la clase. Los miembros privados son solo estado interno de caja negra.
Petter Nordlander
+1 porque me gusta declarar privado incluso si no es necesario. Un buen código tiene mucho que ver con la legibilidad, al igual que la funcionalidad.
PhillyNJ
2
-1 Usar protegido como predeterminado es un consejo horrible. Siempre puede aumentar la visibilidad de los miembros más tarde, pero no al revés, sin descifrar el código (cuando las personas usan su código).
Oliver Weiler