Declarar una matriz const


¿Es posible escribir algo similar a lo siguiente?

public const string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
Author: Kirill Kobelev, 2011-02-28

13 answers

Sí, pero necesitas declararlo readonly en lugar de const:

public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };

La razón es que const solo se puede aplicar a un campo cuyo valor se conoce en tiempo de compilación. El inicializador de matriz que ha mostrado no es una expresión constante en C#, por lo que produce un error de compilador.

Declararlo readonly resuelve ese problema porque el valor no se inicializa hasta el tiempo de ejecución (aunque se garantiza que se inicializará antes de la primera vez que se use el array).

Dependiendo de lo que en última instancia desea lograr, también podría considerar declarar una enumeración:

public enum Titles { German, Spanish, Corrects, Wrongs };
 522
Author: Cody Gray,
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-03-11 13:34:36

Puede declarar array como readonly, pero tenga en cuenta que puede cambiar el elemento de readonly array.

public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
...
Titles[0] = "bla";

Considere usar enum, como Cody sugirió, o IList.

public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
 47
Author: Branimir,
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-02-28 13:33:50

No puede crear una matriz 'const' porque las matrices son objetos y solo pueden ser las entidades creadas en tiempo de ejecución y const se resuelven en tiempo de compilación.

Lo que puede hacer en su lugar es declarar su matriz como "readonly". Esto tiene el el mismo efecto que const, excepto que el valor se puede establecer en tiempo de ejecución. Sólo puede ser se establece una vez y luego es un valor readonly (es decir, const).

 37
Author: JAiro,
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-02-28 13:08:13

Podría tomar un enfoque diferente: definir una cadena constante para representar su matriz y luego dividir la cadena en una matriz cuando lo necesite, por ejemplo,

const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');

Este enfoque le da una constante que se puede almacenar en configuración y convertir en una matriz cuando sea necesario.

Alastair

 6
Author: Alastair,
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
2013-09-26 10:54:31

Para mis necesidades defino static array, en lugar de impossible const y funciona: public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };

 5
Author: ALZ,
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
2013-04-24 14:12:06

Desde C # 6 puedes escribirlo como:

public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" };

Ver también: C # : El Nuevo y Mejorado C # 6.0 (específicamente el capítulo "Funciones y Propiedades con Cuerpo de expresión")

Esto creará una propiedad estática de solo lectura, pero todavía le permitirá alterar el contenido de la matriz devuelta, pero cuando llame a la propiedad de nuevo, obtendrá la matriz original, inalterada de nuevo.

Para aclaración, este código es el mismo que (o en realidad una abreviatura para):

public static string[] Titles
{
    get { return new string[] { "German", "Spanish", "Corrects", "Wrongs" }; }
}

Tenga en cuenta que hay un inconveniente en este enfoque: Una nueva matriz se instanciaen realidad en todas y cada una de las referencias, por lo que si está utilizando una matriz muy grande, esta podría no ser la solución más eficiente. Pero si reutiliza la misma matriz (poniéndola en un atributo privado, por ejemplo) volverá a abrir la posibilidad de cambiar el contenido de la matriz.

Si quieres tener una matriz inmutable (o lista) también puedes usar:

public static IReadOnlyList<string> Titles { get; } = new string[] { "German", "Spanish", "Corrects", "Wrongs" };

Pero, esto todavía tiene un riesgo de cambios, ya que todavía se puede convertir en una cadena[] y alterar el contenido, como tal:

((string[]) Titles)[1] = "French";
 5
Author: mjepson,
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-08-09 14:37:39

Esta es una manera de hacer lo que quieres:

using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;

public ReadOnlyCollection<string> Titles { get { return new List<string> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}

Es muy similar a hacer una matriz de solo lectura.

 4
Author: tdbeckett,
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-05-07 13:36:12

A . NET Framework v4. 5+ solution que mejora la respuesta de tdbeckett :

using System.Collections.ObjectModel;

// ...

public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
  new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);

Nota: Dado que la colección es conceptualmente constante, puede tener sentido hacer static declararla en el nivel class.

Lo anterior:

  • Inicializa el campo de respaldo implícito de la propiedad una vez con la matriz.

    • Tenga en cuenta que { get; } - es decir, declarar solo una propiedad getter - es lo que hace que la propiedad en sí sea implícitamente de solo lectura (tratar de combinar readonly con { get; } es en realidad un error de sintaxis).

    • Alternativamente, puede omitir el { get; } y agregar readonly para crear un field en lugar de una propiedad, como en la pregunta, pero exponer public data members como propiedades en lugar de campos es un buen hábito para formar.

  • Crea una estructura similar a un array (permitiendo acceso indexado) que es verdadera y sólidamente de solo lectura (conceptualmente, constante, una vez creado), ambos con respecto a:

    • impedir la modificación de la colección (por ejemplo, eliminando o añadiendo elementos, o sustituyendo la colección en su conjunto)
    • impedir la modificación de elementos individuales.
      (Even indirect modification isn't possible-unlike with a IReadOnlyList<T> solution, where a (string[]) cast can be used to gain write access to the elements, as se muestra en la útil respuesta de mjepsen .
      La misma vulnerabilidad se aplica a la interfaz IReadOnlyCollection<T>, que, a pesar de su similitud de nombre con la clase ReadOnlyCollection, ni siquiera soporta acceso indexado, por lo que es fundamentalmente inadecuado para proporcionar acceso tipo array).
 3
Author: mklement0,
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-05-23 12:18:01

Si declara una matriz detrás de una interfaz IReadOnlyList, obtiene una matriz constante con valores constantes que se declara en tiempo de ejecución:

public readonly IReadOnlyList<string> Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" };

Disponible en.NET 4.5 y versiones posteriores.

 3
Author: Richard Garside,
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 09:32:31

Creo que solo se puede leer.

 2
Author: skaz,
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-02-28 13:06:44

Los arrays son probablemente una de esas cosas que solo se pueden evaluar en ejecución. Las constantes deben ser evaluadas en tiempo de compilación. Intente usar " readonly" en lugar de "const".

 1
Author: nemke,
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-02-28 13:07:45

Como alternativa, para evitar el problema de los elementos que se pueden modificar con una matriz de solo lectura, puede usar una propiedad estática en su lugar. (Los elementos individuales todavía se pueden cambiar, pero estos cambios solo se realizarán en la copia local del array.)

public static string[] Titles 
{
    get
    {
        return new string[] { "German", "Spanish", "Corrects", "Wrongs"};
    }
}

Por supuesto, esto no será particularmente eficiente ya que se crea una nueva matriz de cadenas cada vez.

 1
Author: Hutch,
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-22 23:08:43

Por el bien de la integridad, ahora también tenemos inmutables rayas a nuestra disposición. Esto debería ser verdaderamente inmutable:

public readonly static ImmutableArray<string> Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });

Requiere Sistema.Colecciones.Referencia inmutable de NuGet

Https://msdn.microsoft.com/en-us/library/mt452182 (v=vs.111). aspx

 0
Author: shurik,
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
2018-07-25 22:54:38