¿Por qué debería evitar el uso de Propiedades en C #?

102

En su excelente libro, CLR Via C #, Jeffrey Richter dijo que no le gustan las propiedades y recomienda no usarlas. Dio alguna razón, pero realmente no entiendo. ¿Alguien puede explicarme por qué debería o no debería utilizar propiedades? En C # 3.0, con propiedades automáticas, ¿esto cambia?

Como referencia agregué las opiniones de Jeffrey Richter:

• Una propiedad puede ser de solo lectura o de solo escritura; el acceso al campo es siempre legible y escribible. Si define una propiedad, es mejor ofrecer métodos de acceso get y set.

• Un método de propiedad puede generar una excepción; el acceso al campo nunca lanza una excepción.

• Una propiedad no se puede pasar como parámetro de salida o referencia a un método; un campo puede. Por ejemplo, el siguiente código no se compilará:

using System;
public sealed class SomeType
{
   private static String Name 
   {
     get { return null; }
     set {}
   }
   static void MethodWithOutParam(out String n) { n = null; }
   public static void Main()
   {
      // For the line of code below, the C# compiler emits the following:
      // error CS0206: A property or indexer may not
      // be passed as an out or ref parameter
      MethodWithOutParam(out Name);
   }
}

• Un método de propiedad puede tardar mucho en ejecutarse; el acceso al campo siempre se completa inmediatamente. Una razón común para usar propiedades es realizar la sincronización de subprocesos, que puede detener el subproceso para siempre y, por lo tanto, no se debe utilizar una propiedad si se requiere sincronización de subprocesos. En esa situación, se prefiere un método. Además, si se puede acceder a su clase de forma remota (por ejemplo, su clase se deriva de System.MashalByRefObject), llamar al método de propiedad será muy lento y, por lo tanto, se prefiere un método a una propiedad. En mi opinión, las clases derivadas de MarshalByRefObject nunca deberían usar propiedades.

• Si se llama varias veces seguidas, un método de propiedad puede devolver un valor diferente cada vez; un campo devuelve el mismo valor cada vez. La clase System.DateTime tiene una propiedad Now de solo lectura que devuelve la fecha y hora actuales. Cada vez que consulte esta propiedad, devolverá un valor diferente. Esto es un error, y Microsoft desea poder arreglar la clase haciendo de Now un método en lugar de una propiedad.

• Un método de propiedad puede causar efectos secundarios observables; el acceso al campo nunca lo hace. En otras palabras, un usuario de un tipo debería poder establecer varias propiedades definidas por un tipo en cualquier orden que elija sin notar ningún comportamiento diferente en el tipo.

• Un método de propiedad puede requerir memoria adicional o devolver una referencia a algo que en realidad no es parte del estado del objeto, por lo que modificar el objeto devuelto no tiene ningún efecto sobre el objeto original; consultar un campo siempre devuelve una referencia a un objeto que está garantizado como parte del estado del objeto original. Trabajar con una propiedad que devuelve una copia puede resultar muy confuso para los desarrolladores y esta característica no suele estar documentada.

Quan Mai
fuente
11
Soy dueño de la tercera edición de 'CLR vía C #' y en la página 242 el Sr. Richter dice que personalmente no le gustan las propiedades, pero nunca recomienda no usarlas. Por favor, cite la versión del libro y el número de página donde leyó esto.
kirk.burleson

Respuestas:

173

La razón de Jeff para no gustarle las propiedades es que parecen campos, por lo que los desarrolladores que no entienden la diferencia los tratarán como si fueran campos, asumiendo que serán baratos de ejecutar, etc.

Personalmente, no estoy de acuerdo con él en este punto en particular: creo que las propiedades hacen que el código del cliente sea mucho más simple de leer que las llamadas al método equivalente. Estoy de acuerdo en que los desarrolladores necesitan saber que las propiedades son básicamente métodos disfrazados, pero creo que educar a los desarrolladores sobre eso es mejor que hacer que el código sea más difícil de leer usando métodos. (En particular, habiendo visto el código Java con varios getters y setters que se llaman en la misma declaración, sé que el código C # equivalente sería mucho más simple de leer. La Ley de Demeter está muy bien en teoría, pero a veces foo.Name.Lengthrealmente lo es lo correcto para usar ...)

(Y no, las propiedades implementadas automáticamente no cambian nada de esto).

Esto se parece un poco a los argumentos en contra del uso de métodos de extensión: puedo entender el razonamiento, pero el beneficio práctico (cuando se usa con moderación) supera la desventaja en mi opinión.

Jon Skeet
fuente
¡Muchas gracias por tu respuesta! Acerca de los argumentos en contra del uso de métodos de extensión: ¿estás hablando de algún tema de Jeffrey Richter o en abstracto?
abatishchev
@abatishchev: Fue solo un punto general sobre los métodos de extensión. No está directamente relacionado con las propiedades.
Jon Skeet
Yo iría más lejos. Excepto por el aspecto de rendimiento, no veo por qué un programador debería SABER si algo es un campo o una propiedad. Debe pensar en él como un atributo de instancia que designa el ESTADO de la instancia del objeto, y la implementación del objeto debe hacerse cargo de todas las modificaciones a su estado (dentro del contrato de la clase). Entonces, las propiedades podrían ser campos en algunos casos, o convertirse en campos en otros, si tal vez se hace un rediseño de la implementación de la clase. Entonces, decidir entre un campo o una propiedad es una cuestión de cuánta protección necesita el estado para mantenerse consistente.
TheBlastOne
1
@PatrickFromberg: Al parecer, se ha perdido una gran cantidad de código que usa campos de solo lectura. No hay nada que decir que las propiedades implican mutabilidad. A menudo tengo campos de solo lectura que respaldan propiedades de solo lectura, ¿cree que eso es algo malo?
Jon Skeet
1
@Patrick: No, trae el beneficio de separar la API de la implementación - luego puede cambiar cómo se calcula la propiedad desde el campo (por ejemplo, para calcular dos propiedades relacionadas desde un campo).
Jon Skeet
34

Bueno, tomemos sus argumentos uno por uno:

Una propiedad puede ser de solo lectura o de solo escritura; el acceso al campo es siempre legible y escribible.

Esto es una ventaja para las propiedades, ya que tiene un control de acceso más detallado.

Un método de propiedad puede generar una excepción; el acceso al campo nunca lanza una excepción.

Si bien esto es cierto en su mayor parte, puede llamar a un método en un campo de objeto no inicializado y generar una excepción.

• Una propiedad no se puede pasar como parámetro de salida o referencia a un método; un campo puede.

Justa.

• Un método de propiedad puede tardar mucho en ejecutarse; el acceso al campo siempre se completa inmediatamente.

También puede llevar muy poco tiempo.

• Si se llama varias veces seguidas, un método de propiedad puede devolver un valor diferente cada vez; un campo devuelve el mismo valor cada vez.

No es verdad. ¿Cómo sabe que el valor del campo no ha cambiado (posiblemente por otro hilo)?

La clase System.DateTime tiene una propiedad Now de solo lectura que devuelve la fecha y hora actuales. Cada vez que consulte esta propiedad, devolverá un valor diferente. Esto es un error, y Microsoft desea poder arreglar la clase haciendo de Now un método en lugar de una propiedad.

Si es un error, es menor.

• Un método de propiedad puede causar efectos secundarios observables; el acceso al campo nunca lo hace. En otras palabras, un usuario de un tipo debería poder establecer varias propiedades definidas por un tipo en cualquier orden que elija sin notar ningún comportamiento diferente en el tipo.

Justa.

• Un método de propiedad puede requerir memoria adicional o devolver una referencia a algo que en realidad no es parte del estado del objeto, por lo que modificar el objeto devuelto no tiene ningún efecto sobre el objeto original; consultar un campo siempre devuelve una referencia a un objeto que está garantizado como parte del estado del objeto original. Trabajar con una propiedad que devuelve una copia puede resultar muy confuso para los desarrolladores y esta característica no suele estar documentada.

La mayoría de las protestas también se podrían decir de los getters y setters de Java, y las tuvimos durante bastante tiempo sin tales problemas en la práctica.

Creo que la mayoría de los problemas se podrían resolver con un mejor resaltado de sintaxis (es decir, diferenciando las propiedades de los campos) para que el programador sepa qué esperar.

Hejazzman
fuente
3
"Los problemas podrían resolverse con un mejor resaltado de sintaxis" : ¿Con qué frecuencia utiliza campos públicos? Los campos privados suelen tener un estilo diferente, por ejemplo _field. O incluso en minúsculas field.
Steven Jeuris
18

No he leído el libro y no has citado la parte que no entiendes, así que tendré que adivinar.

A algunas personas no les gustan las propiedades porque pueden hacer que su código haga cosas sorprendentes.

Si escribo Foo.Bar, las personas que lo lean normalmente esperarán que simplemente acceda a un campo miembro de la clase Foo. Es una operación barata, casi gratuita y determinista. Puedo repetirlo una y otra vez y obtener el mismo resultado cada vez.

En cambio, con propiedades, en realidad podría ser una llamada a función. Podría ser un bucle infinito. Podría abrir una conexión a la base de datos. Puede devolver valores diferentes cada vez que accedo a él.

Es un argumento similar a por qué Linus odia C ++. Su código puede resultar sorprendente para el lector. Odia la sobrecarga del operador: a + bno significa necesariamente una simple adición. Puede significar una operación enormemente complicada, como las propiedades de C #. Puede tener efectos secundarios. Puede hacer cualquier cosa.

Honestamente, creo que este es un argumento débil. Ambos idiomas están llenos de cosas como esta. (¿Deberíamos evitar la sobrecarga de operadores en C # también? Después de todo, se puede usar el mismo argumento allí)

Las propiedades permiten la abstracción. Podemos fingir que algo es un campo normal y usarlo como si lo fuera, y no tener que preocuparnos por lo que sucede detrás de escena.

Eso generalmente se considera algo bueno, pero obviamente se basa en que el programador escriba abstracciones significativas. Tus propiedades deberían comportarse como campos. No deberían tener efectos secundarios, no deberían realizar operaciones costosas o inseguras. Queremos poder pensar en ellos como campos.

Sin embargo, tengo otra razón para encontrarlos menos que perfectos. No se pueden pasar por referencia a otras funciones.

Los campos se pueden pasar como ref, lo que permite que una función llamada acceda a ellos directamente. Las funciones se pueden pasar como delegados, lo que permite que una función llamada acceda a ella directamente.

Propiedades ... no puedo.

Eso apesta.

Pero eso no significa que las propiedades sean malas o no deban usarse. Para muchos propósitos, son geniales.

jalf
fuente
3
Mi argumento es que no debes asumir que es un campo para empezar, porque si lo estás llamando desde cualquier otra clase, no deberías tener acceso a campos no constantes de todos modos, porque deberían ser privados. (También está la convención de nombres para informarle.)
Jon Skeet
1
Si estoy de acuerdo. El argumento parece reducirse a "Estoy acostumbrado a que esta sintaxis se use únicamente para campos. Por lo tanto, extenderla para cubrir otros casos es malo". Y la respuesta obvia es "Bueno, acostúmbrate a que cubra otros casos entonces, y no estará mal". ;)
jalf
Deseo que los lenguajes .net proporcionen un medio estándar por el cual una clase exponga propiedades como refparámetros; un miembro (por ejemplo Foo) de un formulario void Foo<T>(ActionByRef<Point,T> proc, ref T param)con un atributo especial, y hacer que el compilador se transforme thing.Foo.X+=someVar;en Foo((ref Point it, ref int param)=>it.X += param, ref someVar);. Dado que lambda es un delegado estático, no se requeriría ningún cierre y el usuario de un objeto podría usar cualquier ubicación de almacenamiento que respalde la propiedad como un refparámetro genuino (y podría pasarla a otros métodos como refparámetro).
supercat
Escribir la lambda a mano produce un código fuente de aspecto realmente desagradable, pero es por eso que sería útil que el compilador realice la transformación. El código para que una clase exponga una propiedad "callback-by-ref" sería bastante razonable. El código es solo feo (sin una transformación) en el lado de la persona que llama.
supercat
Por favor, comprenda que una propiedad es una llamada a función disfrazada de miembro, por lo que no se puede pasar por referencia más de lo que no se pueden pasar las funciones públicas de una clase. Siempre puede usar miembro público si tiene la intención de hacerlo de esa manera. Una propiedad es un miembro inteligente, puede lanzar una excepción para los datos no válidos pasados ​​al conjunto.
Diceyus
17

En 2009, este consejo simplemente parecía una queja de la variedad Who Moved My Cheese . Hoy en día, es casi ridículamente obsoleto.

Un punto muy importante que muchas respuestas parecen andar de puntillas, pero que no abordan de frente es que estos supuestos "peligros" de las propiedades son una parte intencional del diseño del marco.

Sí, las propiedades pueden:

  • Especifique diferentes modificadores de acceso para el captador y el definidor. Esta es una ventaja sobre los campos. Un patrón común es tener un captador público y un definidor interno o protegido , una técnica de herencia muy útil que no se puede lograr solo con campos.

  • Lanza una excepción. Hasta la fecha, este sigue siendo uno de los métodos de validación más efectivos, especialmente cuando se trabaja con marcos de interfaz de usuario que involucran conceptos de enlace de datos. Es mucho más difícil asegurarse de que un objeto permanezca en un estado válido cuando se trabaja con campos.

  • Tarda mucho en ejecutarse. La comparación válida aquí es con métodos , que toman el mismo tiempo, no con campos . No se da ninguna base para la afirmación "se prefiere un método" que no sea la preferencia personal de un autor.

  • Devuelve valores diferentes de su getter en ejecuciones posteriores. Esto casi parece una broma en una proximidad tan cercana al punto de ensalzar las virtudes de los parámetros ref/ outcon campos, cuyo valor de un campo después de una llamada ref/ outestá prácticamente garantizado que será diferente de su valor anterior, y de manera impredecible.

    Si estamos hablando del caso específico (y prácticamente académico) del acceso de un solo subproceso sin acoplamientos aferentes, se comprende bastante bien que es solo un mal diseño de propiedad el tener efectos secundarios de cambio de estado visible, y tal vez mi memoria es se desvanece, pero parece que no puedo recordar ningún ejemplo de personas que usan DateTime.Nowy esperan que salga el mismo valor cada vez. Al menos no en ningún caso en el que no lo hubieran estropeado tanto con una hipótesis DateTime.Now().

  • Causar efectos secundarios observables, que es, por supuesto, precisamente la razón por la que las propiedades se inventaron en primer lugar como una característica del lenguaje. Las propias pautas de diseño de propiedades de Microsoft indican que el orden de los establecedores no debería importar, ya que hacerlo de otra manera implicaría un acoplamiento temporal . Ciertamente, no puede lograr el acoplamiento temporal con campos solo, pero eso es solo porque no puede hacer que ocurra ningún comportamiento significativo con campos solo, hasta que se ejecute algún método.

    Los descriptores de acceso a la propiedad pueden ayudar a prevenir ciertos tipos de acoplamiento temporal al forzar el objeto a un estado válido antes de que se lleve a cabo cualquier acción; por ejemplo, si una clase tiene un StartDatey un EndDate, entonces establecer el EndDateantes del StartDatepodría forzar el StartDateretroceso también. Esto es cierto incluso en entornos asíncronos o de subprocesos múltiples, incluido el ejemplo obvio de una interfaz de usuario basada en eventos.

Otras cosas que pueden hacer las propiedades y que los campos no pueden incluir:

  • Carga diferida , una de las formas más efectivas de prevenir errores de orden de inicialización.
  • Notificaciones de cambios , que son prácticamente la base completa de la arquitectura MVVM .
  • La herencia , por ejemplo, la definición de clases abstractas Typeo Namederivadas puede proporcionar metadatos interesantes pero constantes sobre sí mismos.
  • Intercepción , gracias a lo anterior.
  • Indexadores , que todos los que alguna vez han tenido que trabajar con interoperabilidad COM y la inevitable oleada de Item(i)llamadas reconocerán como algo maravilloso.
  • Trabaje con PropertyDescriptor, que es esencial para crear diseñadores y para marcos XAML en general.

Richter es claramente un autor prolífico y sabe mucho sobre CLR y C #, pero tengo que decir que parece que cuando escribió originalmente este consejo (no estoy seguro de si está en sus revisiones más recientes, espero sinceramente que no) que simplemente no quería dejar atrás los viejos hábitos y estaba teniendo problemas para aceptar las convenciones de C # (vs. C ++, por ejemplo).

Lo que quiero decir con esto es que su argumento de "propiedades consideradas dañinas" esencialmente se reduce a una sola declaración: las propiedades parecen campos, pero pueden no actuar como campos. Y el problema con la afirmación es que no es verdad o, en el mejor de los casos, es muy engañoso. Las propiedades no parecen campos; al menos, se supone que no deben verse como campos.

Hay dos convenciones de codificación muy fuertes en C # con convenciones similares compartidas por otros lenguajes CLR, y FXCop le gritará si no las sigue:

  1. Los campos siempre deben ser privados, nunca públicos.
  2. Los campos deben declararse en camelCase. Las propiedades son PascalCase.

Por lo tanto, no hay ambigüedad sobre si Foo.Bar = 42es un descriptor de acceso de propiedad o un descriptor de acceso de campo. Es un descriptor de acceso de propiedad y debe tratarse como cualquier otro método: puede ser lento, puede generar una excepción, etc. Esa es la naturaleza de la abstracción : depende totalmente de la discreción de la clase declarante cómo reaccionar. Los diseñadores de clases deben aplicar el principio de la mínima sorpresa, pero las personas que llaman no deben asumir nada sobre una propiedad, excepto que hace lo que dice en la lata. Eso es a propósito.

La alternativa a las propiedades son los métodos getter / setter en todas partes. Ese es el enfoque de Java y ha sido controvertido desde el principio . Está bien si ese es tu bolso, pero no es así como nos movemos en el campo de .NET. Intentamos, al menos dentro de los límites de un sistema de tipo estático, evitar lo que Fowler llama ruido sintáctico . No queremos paréntesis adicionales, adicionales get/ setverrugas, o firmas de métodos adicionales - No si podemos evitarlos sin pérdida de claridad.

Di lo que quieras, pero foo.Bar.Baz = quux.Answers[42]siempre será mucho más fácil de leer que foo.getBar().setBaz(quux.getAnswers().getItem(42)). Y cuando lee miles de líneas de esto al día, marca la diferencia.

(Y si su respuesta natural al párrafo anterior es decir, "seguro que es difícil de leer, pero sería más fácil si lo dividiera en varias líneas", entonces lamento decir que no entendió por completo .)

Aaronaught
fuente
11

No veo ninguna razón por la que no debería usar Propiedades en general.

Las propiedades automáticas en C # 3+ solo simplifican un poco la sintaxis (al estilo del azúcar sintético).

Konstantin Tarkus
fuente
por favor, lea las páginas 215-216 de ese libro. ¡Estoy seguro de que sabes quién es Jeffrey Richter!
Quan Mai
He leído (CLR via C #, 2nd Ed.), ¡No estoy de acuerdo con su posición y no veo razones reales para no usar propiedades!
abatishchev
Es un buen libro, pero no estoy de acuerdo con el autor en este momento.
Konstantin Tarkus
¿Dónde está exactamente ese lugar donde el autor sugiere no usar Propiedades? No he encontrado nada en p.215-217
Konstantin Tarkus
Agregué las opiniones de Jeffrey en mi pregunta :). Puede encontrarlo en las páginas 215-216 en la edición impresa :)
Quan Mai
9

Es solo la opinión de una persona. He leído bastantes libros de C # y todavía no he visto a nadie que diga "no usar propiedades".

Personalmente, creo que las propiedades son una de las mejores cosas de c #. Le permiten exponer el estado a través de cualquier mecanismo que desee. Puede crear una instancia perezosamente la primera vez que se usa algo y puede hacer la validación al establecer un valor, etc. Al usarlas y escribirlas, pienso en las propiedades como establecedores y captadores que tienen una sintaxis mucho mejor.

En cuanto a las advertencias con las propiedades, hay un par. Uno es probablemente un mal uso de propiedades, el otro puede ser sutil.

En primer lugar, las propiedades son tipos de métodos. Puede resultar sorprendente si coloca lógica complicada en una propiedad porque la mayoría de los usuarios de una clase esperan que la propiedad sea bastante ligera.

P.ej

public class WorkerUsingMethod
{
   // Explicitly obvious that calculation is being done here
   public int CalculateResult()
   { 
      return ExpensiveLongRunningCalculation();
   }
}

public class WorkerUsingProperty
{
   // Not at all obvious.  Looks like it may just be returning a cached result.
   public int Result
   {
       get { return ExpensiveLongRunningCalculation(); }
   }
}

Encuentro que usar métodos para estos casos ayuda a hacer una distinción.

En segundo lugar, y lo que es más importante, las propiedades pueden tener efectos secundarios si las evalúa durante la depuración.

Digamos que tiene una propiedad como esta:

public int Result 
{ 
   get 
   { 
       m_numberQueries++; 
       return m_result; 
   } 
}

Ahora suponga que tiene una excepción que ocurre cuando se realizan demasiadas consultas. ¿Adivina qué sucede cuando comienzas a depurar y traspasar la propiedad en el depurador? Cosas malas. ¡Evite hacer esto! Mirar la propiedad cambia el estado del programa.

Estas son las únicas salvedades que tengo. Creo que los beneficios de las propiedades superan con creces los problemas.

Mark Simpson
fuente
6

Esa razón debe haberse dado en un contexto muy específico. Por lo general, es al revés: se recomienda usar propiedades, ya que le brindan un nivel de abstracción que le permite cambiar el comportamiento de una clase sin afectar a sus clientes ...

Rashack
fuente
+1 por destacar implícitamente la importancia del "contrato" entre el cliente y la propiedad de la clase.
TheBlastOne
6

No puedo evitar elegir los detalles de las opiniones de Jeffrey Richter:

Una propiedad puede ser de solo lectura o de solo escritura; el acceso al campo es siempre legible y escribible.

Incorrecto: los campos se pueden marcar como de solo lectura, por lo que solo el constructor del objeto puede escribir en ellos.

Un método de propiedad puede generar una excepción; el acceso al campo nunca lanza una excepción.

Incorrecto: la implementación de una clase puede cambiar el modificador de acceso de un campo de público a privado. Los intentos de leer campos privados en tiempo de ejecución siempre darán como resultado una excepción.

Cecil tiene un nombre
fuente
5

No estoy de acuerdo con Jeffrey Richter, pero puedo adivinar por qué no le gustan las propiedades (no he leído su libro).

Aunque las propiedades son como métodos (en cuanto a implementación), como usuario de una clase, espero que sus propiedades se comporten "más o menos" como un campo público, por ejemplo:

  • no hay ninguna operación que lleve mucho tiempo dentro del captador / definidor de la propiedad
  • el captador de propiedades no tiene efectos secundarios (llamarlo varias veces, no cambia el resultado)

Desafortunadamente, he visto propiedades que no se comportaron de esa manera. Pero el problema no son las propiedades en sí mismas, sino las personas que las implementaron. Entonces solo requiere algo de educación.

M4N
fuente
1
+1 ya que destaca la importancia de un contrato limpio. Tener una propiedad aparentemente de solo lectura que devuelve regularmente un valor diferente en cada referencia es una propiedad de lectura y escritura; simplemente no escribe en su propio valor, sino en otras variables de instancia (directa o indirectamente). Ese no es un mal estilo, pero debe estar documentado (o ser una parte implícita del contrato).
TheBlastOne
4

Hay un momento en el que considero no usar propiedades, y eso es al escribir el código .Net Compact Framework. El compilador CF JIT no realiza la misma optimización que el compilador JIT de escritorio y no optimiza los accesos de propiedades simples, por lo que en este caso agregar una propiedad simple provoca una pequeña cantidad de código sobre el uso de un campo público. Por lo general, esto no sería un problema, pero casi siempre en el mundo de Compact Framework se enfrenta a limitaciones de memoria estrictas, por lo que incluso pequeños ahorros como este cuentan.

Steve
fuente
4

No debe evitar usarlos, pero debe usarlos con calificación y cuidado, por las razones dadas por otros colaboradores.

Una vez vi una propiedad llamada algo así como Clientes que internamente abrían una llamada fuera de proceso a una base de datos y leían la lista de clientes. El código del cliente tenía un 'for (int i to Customers.Count)' que estaba provocando una llamada separada a la base de datos en cada iteración y para el acceso del Cliente seleccionado. Ese es un ejemplo atroz que demuestra el principio de mantener la propiedad muy liviana, rara vez más que un acceso de campo interno.

Un argumento para usar propiedades es que le permiten validar el valor que se establece. Otra es que el valor de la propiedad puede ser un valor derivado, no un solo campo, como TotalValue = cantidad * cantidad.

Rob Kent
fuente
3

Personalmente, solo uso propiedades cuando creo métodos simples de obtención / configuración. Me desvío de él cuando llego a estructuras de datos complicadas.

Steve
fuente
3

El argumento asume que las propiedades son malas porque parecen campos, pero pueden realizar acciones sorprendentes. Esta suposición queda invalidada por las expectativas de los programadores de .NET:

Las propiedades no parecen campos. Los campos parecen propiedades.

• Un método de propiedad puede generar una excepción; el acceso al campo nunca lanza una excepción.

Por lo tanto, un campo es como una propiedad que está garantizada para no generar nunca una excepción.

• Una propiedad no se puede pasar como parámetro de salida o referencia a un método; un campo puede.

Entonces, un campo es como una propiedad, pero tiene capacidades adicionales: pasar a métodos ref/ outaccept.

• Un método de propiedad puede tardar mucho en ejecutarse; el acceso al campo siempre se completa inmediatamente. [...]

Entonces, un campo es como una propiedad rápida.

• Si se llama varias veces seguidas, un método de propiedad puede devolver un valor diferente cada vez; un campo devuelve el mismo valor cada vez. La clase System.DateTime tiene una propiedad Now de solo lectura que devuelve la fecha y hora actuales.

Por lo tanto, un campo es como una propiedad que está garantizada para devolver el mismo valor a menos que el campo se establezca en un valor diferente.

• Un método de propiedad puede causar efectos secundarios observables; el acceso al campo nunca lo hace.

Nuevamente, un campo es una propiedad que está garantizada para no hacer eso.

• Un método de propiedad puede requerir memoria adicional o devolver una referencia a algo que en realidad no es parte del estado del objeto, por lo que modificar el objeto devuelto no tiene ningún efecto sobre el objeto original; consultar un campo siempre devuelve una referencia a un objeto que está garantizado como parte del estado del objeto original. Trabajar con una propiedad que devuelve una copia puede resultar muy confuso para los desarrolladores y esta característica no suele estar documentada.

Este puede ser sorprendente, pero no porque sea una propiedad que lo haga. Más bien, es que casi nadie devuelve copias mutables en las propiedades, por lo que el caso del 0.1% es sorprendente.

milenio
fuente
0

La invocación de métodos en lugar de propiedades reduce en gran medida la legibilidad del código de invocación. En J #, por ejemplo, usar ADO.NET era una pesadilla porque Java no admite propiedades e indexadores (que son esencialmente propiedades con argumentos). El código resultante era extremadamente feo, con llamadas a métodos de paréntesis vacías por todas partes.

El soporte para propiedades e indexadores es una de las ventajas básicas de C # sobre Java.

Marty Solomon
fuente