Tener un debate amistoso con un compañero de trabajo sobre esto. Tenemos algunas ideas sobre esto, pero nos preguntamos qué piensa la gente de SO sobre esto.
Tener un debate amistoso con un compañero de trabajo sobre esto. Tenemos algunas ideas sobre esto, pero nos preguntamos qué piensa la gente de SO sobre esto.
Respuestas:
Una razón es que no hay soporte CLR para un local de solo lectura. Readonly se traduce en el código de operación de inicio CLR / CLI. Esta bandera solo se puede aplicar a campos y no tiene significado para un local. De hecho, aplicarlo a un local probablemente producirá un código no verificable.
Esto no significa que C # no pueda hacer esto. Pero daría dos significados diferentes a la misma construcción del lenguaje. La versión para locales no tendría un mapeo equivalente a CLR.
readonly
CLI debe admitir la palabra clave para campos porque su efecto es visible para otros ensamblados. Todo lo que significaría es que la variable solo tiene una asignación en el método en el momento de la compilación.
const
(que en C ++ se parece más a C # readonly
que a C # const
, aunque puede desempeñar ambos roles). Sin embargo, C ++ admite const
variables automáticas locales. Por lo tanto, la falta de compatibilidad con CLR para C # readonly
para la variable local es irrelevante.
using
y out
están haciendo exactamente eso y el mundo no se derrumbó.
Creo que es un mal juicio por parte de los arquitectos de C #. El modificador de solo lectura en las variables locales ayuda a mantener la corrección del programa (como afirma) y puede ayudar potencialmente al compilador a optimizar el código (al menos en el caso de otros lenguajes). El hecho de que no esté permitido en C # en este momento es otro argumento de que algunas de las "características" de C # son simplemente una imposición del estilo de codificación personal de sus creadores.
Al abordar la respuesta de Jared, probablemente solo tendría que ser una función en tiempo de compilación: el compilador le prohibiría escribir en la variable después de la declaración inicial (que tendría que incluir una asignación).
¿Puedo ver valor en esto? Potencialmente, pero no mucho, para ser honesto. Si no puede saber fácilmente si se asignará una variable en otro lugar del método, entonces su método es demasiado largo.
Por lo que vale, Java tiene esta característica (usando el final
modificador) y muy pocas veces la he visto usada excepto en los casos en los que tiene que usarse para permitir que la variable sea capturada por una clase interna anónima, y dónde está usado, me da una impresión de desorden en lugar de información útil.
readonly
/ locales final
de las variables con sus palabras clave val
y var
. En el código de Scala, los mensajes de correo electrónico locales val
se utilizan con mucha frecuencia (y, de hecho, se prefieren a los var
mensajes de correo electrónico locales ). Sospecho que las razones principales por las que el final
modificador no se usa con más frecuencia en Java son a) el desorden yb) la pereza.
readonly
no sería demasiado importante. Por otro lado, para las variables locales que se utilizan en cierres, readonly
en muchos casos permitiría al compilador generar código más eficiente. Actualmente, cuando la ejecución entra en un bloque que contiene un cierre, el compilador debe crear un nuevo objeto de montón para las variables cerradas, incluso si nunca se ejecuta ningún código que usaría el cierre . Si una variable fuera de solo lectura, el código fuera del cierre podría usar una variable normal; solo cuando se crea un delegado para el cierre ...
El equipo de diseño de C # 7 discutió brevemente una propuesta de solo lectura local y parámetros . De C # Design Meeting Notes para el 21 de enero de 2015 :
Los parámetros y los valores locales pueden ser capturados por lambdas y, por lo tanto, acceder a ellos simultáneamente, pero no hay forma de protegerlos de problemas de estado mutuo compartido: no pueden ser de solo lectura.
En general, la mayoría de los parámetros y muchos locales nunca deben asignarse después de obtener su valor inicial. Permitir solo lectura en ellos expresaría esa intención con claridad.
Un problema es que esta característica puede ser una "molestia atractiva". Mientras que lo "correcto" sería casi siempre hacer que los parámetros y los locales sean de solo lectura, saturaría el código de manera significativa.
Una idea para aliviar esto en parte es permitir que la combinación de solo lectura var en una variable local se contraiga a val o algo así. De manera más general, podríamos intentar pensar simplemente en una palabra clave más corta que la establecida readonly para expresar el readonly-ness.
La discusión continúa en el repositorio de diseño del lenguaje C #. Vote para mostrar su apoyo. https://github.com/dotnet/csharplang/issues/188
Es un descuido del diseñador del lenguaje C #. F # tiene la palabra clave val y se basa en CLR. No hay ninguna razón por la que C # no pueda tener la misma característica de idioma.
¡Yo era ese compañero de trabajo y no era amigable! (es una broma)
No eliminaría la función porque es mejor escribir métodos cortos. Es un poco como decir que no deberías usar hilos porque son difíciles. Dame el cuchillo y déjame ser responsable de no cortarme.
Personalmente, quería otra palabra clave de tipo "var" como "inv" (invariante) o "rvar" para evitar el desorden. He estado estudiando F # últimamente y encuentro atractivo lo inmutable.
Nunca supe que Java tenía esto.
Me gustaría variables de solo lectura locales de la misma manera que me gustan las variables de const locales . Pero tiene menos prioridad que otros temas.
Tal vez su prioridad sea la misma razón por la que los diseñadores de C # no implementan (¡todavía!) Esta característica. Pero debería ser fácil (y compatible con versiones anteriores) admitir variables de solo lectura locales en versiones futuras.
Solo lectura significa que el único lugar donde se puede establecer la variable de instancia es en el constructor. Cuando se declara una variable localmente, no tiene una instancia (solo está en el alcance) y el constructor no puede tocarla.
Lo sé, esto no responde al por qué de tu pregunta. De todos modos, aquellos que lean esta pregunta podrían apreciar el código a continuación.
Si realmente le preocupa dispararse a sí mismo en el pie al anular una variable local que solo debe establecerse una vez, y no desea convertirla en una variable más accesible globalmente, podría hacer algo como esto.
public class ReadOnly<T>
{
public T Value { get; private set; }
public ReadOnly(T pValue)
{
Value = pValue;
}
public static bool operator ==(ReadOnly<T> pReadOnlyT, T pT)
{
if (object.ReferenceEquals(pReadOnlyT, null))
{
return object.ReferenceEquals(pT, null);
}
return (pReadOnlyT.Value.Equals(pT));
}
public static bool operator !=(ReadOnly<T> pReadOnlyT, T pT)
{
return !(pReadOnlyT == pT);
}
}
Uso de ejemplo:
var rInt = new ReadOnly<int>(5);
if (rInt == 5)
{
//Int is 5 indeed
}
var copyValueOfInt = rInt.Value;
//rInt.Value = 6; //Doesn't compile, setter is private
Quizás no menos código, rvar rInt = 5
pero funciona.
Puede declarar variables locales de solo lectura en C #, si está utilizando el compilador interactivo de C # csi
:
>"C:\Program Files (x86)\MSBuild\14.0\Bin\csi.exe"
Microsoft (R) Visual C# Interactive Compiler version 1.3.1.60616
Copyright (C) Microsoft Corporation. All rights reserved.
Type "#help" for more information.
> readonly var message = "hello";
> message = "goodbye";
(1,1): error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
También puede declarar variables locales de solo lectura en el .csx
formato de script.
message
aquí no hay una variable, se compila en un campo. Esto no es quisquilloso porque la distinción también existe claramente en C # interactivo: int x; Console.WriteLine(x)
es C # interactivo legal (porque x
es un campo e implícitamente inicializado) pero void foo() { int x; Console.WriteLine(x); }
no lo es (porque x
es una variable y se usa antes de ser asignada). Además, Expression<Func<int>> y = x; ((MemberExpression) y.Body).Member.MemberType
revelará que x
realmente es un campo y no una variable local.
c # ya tiene una var de solo lectura, aunque en una sintaxis algo diferente:
Considere las siguientes líneas:
var mutable = myImmutableCalculationMethod();
readonly var immutable = mutable; // not allowed in C# 8 and prior versions
return immutable;
Comparar con:
var mutable = myImmutableCalculationMethod();
string immutable() => mutable; // allowed in C# 7
return immutable();
Es cierto que la primera solución podría ser menos código para escribir. Pero el segundo fragmento hará que la lectura sea explícita al hacer referencia a la variable.
readonly var im = new List<string>(); im.Add("read-only variable, mutable object!");
.
utilizar const
palabra clave para hacer una variable de solo lectura.
referencia: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const
public class SealedTest
{
static void Main()
{
const int c = 707;
Console.WriteLine("My local constant = {0}", c);
}
}
const
donde la variable solo se puede asignar durante su inicialización, no en el estilo csharp, const
donde solo se pueden usar expresiones en tiempo de compilación. Por ejemplo, no puede hacerlo, const object c = new object();
pero un readonly
local le permitiría hacerlo.