¿Por qué C# no permite variables locales de solo lectura?


Tener un debate amistoso con un compañero de trabajo sobre esto. Tenemos algunas ideas sobre esto, pero preguntándose qué piensa la multitud de SO sobre esto?

Author: Ryan Gates, 2009-01-14

12 answers

Una razón es que no hay soporte CLR para un local de solo lectura. Readonly se traduce al opcode initonly de CLR / CLI. Esta bandera solo se puede aplicar a los campos y no tiene significado para un local. De hecho, aplicarlo a un local probablemente producirá 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 una asignación equivalente a CLR.

 13
Author: JaredPar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-14 17:07:41

Creo que es un mal juicio por parte de C# architects. readonly modifier en variables locales ayuda a mantener la corrección del programa (al igual que asserts) y potencialmente puede ayudar 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 aplicación del estilo de codificación personal de sus creadores.

 36
Author: andriej,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-29 14:43:45

Abordando la respuesta de Jared, probablemente solo tendría que ser una característica 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 decir fácilmente si una variable va a ser asignada en otro lugar del método, entonces su método es demasiado largo.

Por si sirve de algo, Java tiene esta característica (usando el modificador final) y he muy rara vez visto que se utiliza, excepto en los casos en que tiene para ser utilizado para permitir que la variable sea capturada por una clase interna anónima - y donde es utilizado, me da una impresión de desorden en lugar de información útil.

 30
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-14 13:51:05

Una propuesta readonly locales y parámetros for fue brevemente discutido por el equipo de diseño de C# 7. From C # Design Meeting Notes for Jan 21, 2015:

Los parámetros y los locales pueden ser capturados por lambdas y, por lo tanto, accedidos simultáneamente, pero no hay forma de protegerlos de los problemas de estado mutuo compartido: no se pueden leer solo.

En general, la mayoría de los parámetros y muchos locales nunca están destinados a ser asignados después de obtener su inicial valor. Permitir solo leerlos expresaría esa intención claramente.

Un problema es que esta característica podría ser una "molestia atractiva". Mientras que la "cosa correcta" a hacer casi siempre sería hacer parámetros y locales de solo lectura, sería saturar el código de manera significativa para hacerlo.

Una idea para aliviar en parte esto es permitir que la combinación readonly var en una variable local se contraiga a val o algo corto como eso. Más generalmente podríamos intentar simplemente piense en una palabra clave más corta que la establecida readonly para expresar la readonly-ness.

La discusión continúa en el repositorio de diseño del lenguaje C#. Vota para mostrar tu apoyo. https://github.com/dotnet/csharplang/issues/188

 12
Author: Colonel Panic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-06 15:02:18

Yo era ese compañero de trabajo y no era amigable! (solo bromeo)

No eliminaría la característica porque es mejor escribir métodos cortos. Es un poco como decir que no debes usar hilos porque son duros. Dame el cuchillo y déjame ser responsable de no cortarme.

Personalmente, quería otra palabra clave de tipo "var" como "inv" (invarient) o "rvar" para evitar el desorden. He estado estudiando F # últimamente y encuentro lo inmutable atractivo.

Nunca supe Java tenía esto.

 7
Author: Mike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-14 17:59:43

Me gustaría local readonlyvariables de la misma manera que me gusta local const variables. Pero tiene menos prioridad que otros temas.
Tal vez su prioridad es la misma razón por la que los diseñadores de C# no (¡todavía!) implementar esta característica. Pero debería ser fácil (y compatible con versiones anteriores) soportar variables locales de solo lectura en futuras versiones.

 5
Author: brgerner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-30 13:20:19

Es un descuido para c# language designer. F # tiene la palabra clave val y se basa en CLR. No hay razón por la que C# no pueda tener la misma función de lenguaje.

 4
Author: Derek Liang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-04 23:13:53

Readonly 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 ámbito), y no puede ser tocada por el constructor.

 3
Author: Jason Punyon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-14 17:08:07

Lo sé, esto no responde el por qué a tu pregunta. De todos modos, aquellos que leen esta pregunta podrían apreciar el código a continuación, no obstante.

Si realmente le preocupa dispararse a sí mismo en el pie cuando anula una variable local que solo debe configurarse una vez, y no desea que sea 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);
        }
    }

Ejemplo de uso:

        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

Tal vez no tanto código como rvar rInt = 5 pero funciona.

 1
Author: Mike de Klerk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-11 05:15:16

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 formato de script .csx.

 0
Author: Colonel Panic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-12 15:25:10

Creo que eso es porque una función que tiene una variable readonly nunca puede ser llamada, y probablemente hay algo acerca de que va fuera de alcance, y ¿cuándo lo necesitarías?

 -2
Author: scottm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-14 16:37:44

Use la palabra clave const 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);
    }
}
 -2
Author: Derek Liang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-17 21:06:30