El punto de la corrección constante es poder proporcionar una vista de una instancia que el usuario no puede alterar ni eliminar. El compilador admite esto al señalar cuando se rompe la constness desde dentro de una función const, o se intenta usar una función no const de un objeto const. Entonces, sin copiar el enfoque const, ¿hay una metodología que pueda usar en C # que tenga los mismos fines?
Soy consciente de la inmutabilidad, pero eso realmente no se traslada a los objetos contenedores, por nombrar solo un ejemplo.
c#
theory
const-correctness
tenpn
fuente
fuente
const_cast
en C #?Respuestas:
También me he encontrado con este problema muchas veces y terminé usando interfaces.
Creo que es importante abandonar la idea de que C # es cualquier forma, o incluso una evolución de C ++. Son dos lenguajes diferentes que comparten casi la misma sintaxis.
Por lo general, expreso 'corrección constante' en C # definiendo una vista de solo lectura de una clase:
public interface IReadOnlyCustomer { String Name { get; } int Age { get; } } public class Customer : IReadOnlyCustomer { private string m_name; private int m_age; public string Name { get { return m_name; } set { m_name = value; } } public int Age { get { return m_age; } set { m_age = value; } } }
fuente
const
, sin el costo adicional de definir una interfaz separada y requerir el envío en tiempo de ejecución. Es decir, el lenguaje proporciona una forma sencilla de implementar interfaces const en tiempo de compilación.const
-ness es parte del diseño y declara la intención con tanta claridad como escribir una interfaz constante externa. Además, proporcionar const-interfaces puede ser una tarea compleja si se tiene que abordar manualmente, y puede requerir escribir casi tantas interfaces como clases estén presentes en el tipo compuesto. Eso nos lleva a tu última frase: 'arruinar las cosas por olvidar agregar la constante'. Es más fácil acostumbrarse a agregar el enconst
todas partes (el costo de desarrollo es pequeño) que escribir interfaces de solo lectura para cada clase.Para obtener el beneficio de la locura constante (o pureza en términos de programación funcional), necesitará diseñar sus clases de manera que sean inmutables, tal como lo es la clase String de c #.
Este enfoque es mucho mejor que marcar un objeto como de solo lectura, ya que con las clases inmutables puede pasar datos fácilmente en entornos multitarea.
fuente
Builder
clases para grandes tipos inmutables (Java y .NET definen laStringBuilder
clase, que es solo un ejemplo).Solo quería señalarle que muchos de los contenedores System.Collections.Generics tienen un método AsReadOnly que le devolverá una colección inmutable.
fuente
C # no tiene esa característica. Puede pasar argumentos por valor o por referencia. La referencia en sí es inmutable a menos que especifique el modificador ref . Pero los datos referenciados no son inmutables. Por lo tanto, debe tener cuidado si desea evitar los efectos secundarios.
MSDN:
Pasar parámetros
fuente
Las interfaces son la respuesta, y en realidad son más poderosas que "const" en C ++. const es una solución única para todos los problemas donde "const" se define como "no establece miembros o llama a algo que establece miembros". Esa es una buena forma abreviada de const-ness en muchos escenarios, pero no en todos. Por ejemplo, considere una función que calcula un valor basado en algunos miembros pero que también almacena en caché los resultados. En C ++, eso se considera no constante, aunque desde la perspectiva del usuario es esencialmente constante.
Las interfaces le brindan más flexibilidad para definir el subconjunto específico de capacidades que desea brindar desde su clase. ¿Quieres constancia? Simplemente proporcione una interfaz sin métodos mutantes. ¿Quiere permitir configurar algunas cosas pero no otras? Proporcione una interfaz solo con esos métodos.
fuente
mutable
.De acuerdo con algunos de los otros, miran el uso de campos de solo lectura que inicializa en el constructor para crear objetos inmutables.
public class Customer { private readonly string m_name; private readonly int m_age; public Customer(string name, int age) { m_name = name; m_age = age; } public string Name { get { return m_name; } } public int Age { get { return m_age; } } }
Alternativamente, también podría agregar un alcance de acceso en las propiedades, es decir, ¿public get y protected set?
public class Customer { private string m_name; private int m_age; protected Customer() {} public Customer(string name, int age) { m_name = name; m_age = age; } public string Name { get { return m_name; } protected set { m_name = value; } } public int Age { get { return m_age; } protected set { m_age = value; } } }
fuente
El problema con readonly es que solo permite que la referencia (puntero) sea constante. La cosa referenciada (señalada) todavía se puede modificar. Esta es la parte complicada, pero no hay forma de evitarlo. Implementar objetos constantes significa hacer que no expongan ningún método o propiedad mutable, pero esto es incómodo.
Consulte también C # efectivo: 50 formas específicas de mejorar su C # (elemento 2: prefiera solo lectura a const.)
fuente