c# - tamaño - Declara una matriz de const
recorrer matriz c# (13)
¿Es posible escribir algo similar a lo siguiente?
public const string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
Como alternativa, para solucionar el problema de los elementos que pueden modificarse con una matriz de solo lectura, puede utilizar una propiedad estática en su lugar. (Los elementos individuales aún se pueden cambiar, pero estos cambios solo se realizarán en la copia local de la matriz).
public static string[] Titles
{
get
{
return new string[] { "German", "Spanish", "Corrects", "Wrongs"};
}
}
Por supuesto, esto no será particularmente eficiente ya que cada vez se crea una nueva cadena de cadenas.
Creo que solo puedes hacerlo solo.
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 expresiones de expresión")
Esto creará una propiedad estática de solo lectura, pero aún así le permitirá alterar el contenido de la matriz devuelta, pero cuando vuelva a llamar a la propiedad, volverá a obtener la matriz original sin alterar.
Para aclarar, este código es el mismo que (o en realidad es una forma abreviada de):
public static string[] Titles
{
get { return new string[] { "German", "Spanish", "Corrects", "Wrongs" }; }
}
Tenga en cuenta que este enfoque tiene un inconveniente: en realidad, se crea una instancia de una nueva matriz en todas y cada una de las referencias, por lo que si utiliza 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), nuevamente se abrirá la posibilidad de cambiar el contenido de la matriz.
Si desea tener una matriz inmutable (o lista) también puede usar:
public static IReadOnlyList<string> Titles { get; } = new string[] { "German", "Spanish", "Corrects", "Wrongs" };
Pero, esto todavía tiene un riesgo de cambios, ya que aún puede volver a convertirlo en una cadena [] y alterar el contenido, como tal:
((string[]) Titles)[1] = "French";
En aras de la integridad, ahora también tenemos ImmutableArrays a nuestra disposición. Esto debería ser verdaderamente inmutable:
public readonly static ImmutableArray<string> Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });
Requiere System.Collections.Immutable referencia de NuGet
https://msdn.microsoft.com/en-us/library/mt452182(v=vs.111).aspx
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.
Las matrices son probablemente una de esas cosas que solo se pueden evaluar en tiempo de ejecución. Las constantes deben ser evaluadas en tiempo de compilación. Intente usar "readonly" en lugar de "const".
No puede crear una matriz ''const'' porque las matrices son objetos y solo se pueden crear en tiempo de ejecución y las entidades const se resuelven en tiempo de compilación.
Lo que puede hacer en su lugar es declarar su matriz como "readonly". Esto tiene el mismo efecto que const, excepto que el valor se puede establecer en tiempo de ejecución. Solo se puede establecer una vez y luego es un valor de solo lectura (es decir, const).
Para mis necesidades defino una matriz static
, en lugar de una const
imposible y funciona: public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
Podría adoptar un enfoque diferente: defina una cadena constante para representar su matriz y luego divida la cadena en una matriz cuando la necesite, por ejemplo
const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split('','');
Este enfoque le brinda una constante que puede almacenarse en la configuración y convertirse en una matriz cuando sea necesario.
Alastair
Puede declarar la matriz como de readonly
, pero tenga en cuenta que puede cambiar el elemento de la matriz de readonly
.
public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
...
Titles[0] = "bla";
Considere el uso de enumeración, como sugirió Cody, o IList.
public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
Sí, pero necesita declararlo de solo readonly
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 compilación.
Declararlo de solo readonly
resuelve ese problema porque el valor no se inicializa hasta el tiempo de ejecución (aunque se garantiza que se haya inicializado antes de la primera vez que se usa la matriz).
Dependiendo de qué es lo que finalmente desea lograr, también podría considerar declarar una enumeración:
public enum Titles { German, Spanish, Corrects, Wrongs };
Si declara una matriz detrás de una interfaz IReadOnlyList, obtiene una matriz constante con valores constantes que se declaran en tiempo de ejecución:
public readonly IReadOnlyList<string> Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" };
Disponible en .NET 4.5 y superior.
Una solución .NET Framework v4.5 + 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 que sea static
declararla a nivel de clase .
Lo anterior:
Inicializa el campo de respaldo implícito de la propiedad una vez con la matriz.
Tenga en cuenta que
{ get; }
{ get; }
- es decir, declarar solo un captador de propiedades - es lo que hace que la propiedad en sí sea implícitamente de solo lectura (tratar de combinarreadonly
con{ get; }
es en realidad un error de sintaxis).Alternativamente, puedes simplemente omitir el
{ get; }
{ get; }
y agreguereadonly
para crear un campo en lugar de una propiedad, como en la pregunta, pero exponer a los miembros de datos públicos como propiedades en lugar de campos es un buen hábito.
Crea una estructura similar a una matriz (que permite el acceso indexado) que es verdadera y robusta de solo lectura (conceptualmente, constante, una vez creada), ambas con respecto a:
- evitar la modificación de la colección (por ejemplo, eliminando o agregando elementos, o reemplazando la colección en su totalidad)
- Prevención de la modificación de elementos individuales.
(Incluso la modificación indirecta no es posible, a diferencia de la soluciónIReadOnlyList<T>
, donde se puede usar unaIReadOnlyList<T>
(string[])
para obtener acceso de escritura a los elementos, como se muestra en la útil respuesta de mjepsen .
La misma vulnerabilidad se aplica a laIReadOnlyCollection<T>
, que, a pesar de su similitud con el nombre de la claseReadOnlyCollection
, ni siquiera admite el acceso indexado , lo que la hace fundamentalmente inadecuada para proporcionar un acceso tipo array.