2012-04-11 12 views
25

Me he estado preguntando por un tiempo por qué C# no es compatible con const en una clase o un nivel de método. Sé que Jon Skeet ha querido soporte para la inmutabilidad durante mucho tiempo, y reconozco que el uso de la sintaxis C++ de la función const podría ayudar en eso. Al agregar una palabra clave const en un nivel de clase tendremos soporte total.¿Por qué el soporte de C# no es const en un nivel de clase/método?

Ahora, mi pregunta es, ¿cuál es la razón para que el equipo de C# no haya desarrollado este tipo de soporte?

Me imagino que todo se podría crear con una verificación en tiempo de compilación o mediante atributos, sin necesidad de cambiar el CLR. No me importa que el código sea capaz de anular el comportamiento constante a través de la reflexión.

Imagínese esto:

const class NumberContainer 
{ 
    public int Number { get; } 
} 

.. Tal clase sólo puede estar ocupados en el tiempo de construcción, por lo que necesitaríamos un constructor de tomar en un int.

Otro ejemplo es const en un nivel de método:

public int AddNumbers(NumberContainer n1, NumberContainer n2) const 
{ 
    return n1.Number + n2.Number; 
} 

métodos de nivel Const no deben ser capaces de alterar el estado en su propia clase o las instancias de los tipos de referencia se pasan a ellos. Además, las funciones de nivel constante solo pueden invocar otras funciones de nivel constante mientras están en su alcance.

No estoy seguro si lambdas y los delegados harían todo demasiado difícil (o imposible) de lograr, pero estoy seguro de que alguien con más experiencia en diseño de lenguaje y compilación podría decirme.

Como Steve B señaló en los comentarios, la existencia de readonly hace las cosas un poco más complejo, como const y readonly están cerca de la misma durante runtime, pero readonly valores no se pueden determinar durante el tiempo de compilación. Supongo que podríamos tener const y readonly de nivel, pero eso podría ser muy confuso.

Entonces, ¿cuál es el motivo para no implementar esto? Las preocupaciones sobre la usabilidad (entender la constness en C++ suele ser bastante difícil para los usuarios nuevos), las preocupaciones sobre el diseño del lenguaje (no se puede hacer) o simplemente las preocupaciones prioritarias (los días de la inmutabilidad-zumbido han terminado)?

+0

¿no maneja la palabra clave 'readonly' su requerimiento? –

+0

Oups, mi mal ... También he pensado mucho en leer solo, pero me olvidé de publicarlo. Actualizaré mi proceso de pensamiento. – cwap

+7

Básicamente, estás preguntando "¿por qué el lenguaje no tiene la función X"? Simple: o bien no se ha propuesto + considerado + aprobado + ámbito + diseñado + implementado + probado + documentado + implementado (comparado con otros usos posibles para ese recurso, y el impacto de la hinchazón del lenguaje), o * algo * de eso fue considerado y fue rechazado como indeseable o diferido. No es automático que cada idioma tenga todas las características imaginables. –

Respuesta

24

Arriesgando una explicación un tanto circular, C# no es compatible con const porque el CLR no tiene soporte para eso en absoluto. El CLR no lo admite porque es drásticamente no compatible con CLS.

Hay muy pocos idiomas que tengan el concepto. El lenguaje C tiene soporte para const, que está bien soportado en C# por readonly palabra clave. Pero el gran perro es, por supuesto, C++ que tiene una aplicabilidad mucho más amplia para const, sin duda la que está buscando. Evitaré determinar qué significa const, ese es un agujero de gusano en sí mismo y solo hablaré de "const-ness", la propiedad de tener const aplicado.

El problema con la const-ness es que tiene que ser forzado. Ese es un problema en C# cuando un lenguaje arbitrario, otro, puede usar una clase C# e ignorar completamente la const-ness solo porque el lenguaje no lo admite. Usarlo en cualquier otro lenguaje CLS simplemente porque C# lo admite es, por supuesto, muy poco práctico.

La aplicabilidad también es un problema en C++. Porque el lenguaje también admite const_cast <>. Cualquier código de cliente puede arrojar la constidad lejos rápidamente y sin diagnosticar. Se supone que no debes hacerlo, pero a veces tienes que hacerlo. Porque hay dos tipos de constidad, estrictos y observables. Aproximadamente análoga a la constidad privada y la constidad pública. La palabra clave mutable se agregó al idioma más tarde para tratar de hacer frente a la necesidad de const-ness observable por lo que al menos el uso inevitable de const_cast <> podría evitarse. Algunas personas dicen que C++ es un lenguaje difícil. No escuches mucho sobre C#.

+0

La mejor respuesta de todas. ¡Muchas gracias, tiene mucho sentido! – cwap

3

Usted dice que no es necesario cambiar el CLR, pero considere que no existe una forma estándar de expresar esta "constidad" dentro de los ensamblajes compilados, y que estos ensamblajes pueden no ser consumidos por el código C# de todos modos. No es algo que pueda solo hacer para C# - tendría que hacerlo para todos los lenguajes .NET.

2

Como creo que el caso sea, const significa cosas diferentes en C# en comparación con C++.

En C# puede utilizar la palabra clave readonly para obtener el nivel de funcionalidad que desea de const.

1

En el caso de que su propuesta de clase const, que dicen:

Tal clase sólo puede estar ocupado en el momento de la construcción, por lo que necesitaría un constructor de tomar en un int

Pero al hacer que todas las propiedades sean solo de lectura, de todos modos ya ha logrado lo que ha dicho.

No puedo hablar de los diseñadores de lenguaje C# pero quizás la razón de no tener const aplicado a muchos otros constructos es porque agregarlo simplemente no valía la pena y puede solucionar el problema de otras maneras (como se describió anteriormente y en otras respuestas/comentarios).

1

No puedo decir por su pregunta, cómo esta sobrecarga de la palabra clave const sería especialmente beneficiosa.

Su primer ejemplo podría reescribirse legalmente como

public class NumberContainer 
{ 
    private readonly int number; 

    public NumberContainer(int number) 
    { 
     this.number = number; 
    } 

    public int Number 
    { 
     get { return number; } 
    } 
} 

Tal vez, si el compilador no es capaz de discernir la inmutabilidad de esta clase (no sé), algún atributo podría ser útil?

En su segundo ejemplo, no entiendo a lo que conduce. Si una función devuelve un valor constante, puede ser reemplazado por un campo constante.

2

que estaba una vez sorprendidos por la siguiente situación:

class Vector 
{ 
    private double[] m_data; 
    public int Dimension {get;set;} 

    public double this[int i] 
    { 
     get {return m_data[i];} 
     set {m_data[i] = value;} 
    } 

    public Vector(int n) 
    { 
     this.Dimension = n; 
     this.m_data = new double(n); 
    } 

    public static Vector Zero(int n) 
    { 
     Vector v = new Vector(n); 
     for (int i = 0; i < n; i++) 
     { 
      v[i] = 0.0; 
     } 

     return v; 
    } 

    public static readonly Vector Zero3 = Zero(3); 
} 

Tú Vector.Zero3 es de sólo lectura y no se puede asignar a la misma, podrá seguir accediendo a su componente, y luego la siguiente cosa estúpida que sucede:

Vector a = Vector.Zero3; 
a[0]  = 2.87; 

y ahora, desde un ist nada más que una referencia a Vector.Vector3 este último también tiene Vector.Vector3 [0] == 2.87!

Después de caer en este pozo una vez, inventé un truco muy simple, aunque no elegante, cumple su función.

A saber, en una clase que supongo que para producir sólo lectura "constantes" estáticos, presento una bandera booleana:

class Vector 
{ 
    private double[] m_data; 
    public int Dimension {get;set;} 
    private bool m_bIsConstant = false; 
    ... 

    public double this[int i] 
    { 
     get {return m_data[i];} 
     set 
     { 
      if (!m_bIsConstant) 
      { 
       m_data[i] = value; 
      } 
     } 
    } 
    ... 
    public static Vector Zero(int n) 
    { 
     Vector v = new Vector(n); 
     for (int i = 0; i < n; i++) 
     { 
      v[i] = 0.0; 
     } 

     v.m_bIsConstant = true; 
     return v; 
    } 
    ... 
} 

Este truco garantías de que su variable de sólo lectura estática no será modificado.

Cuestiones relacionadas