Respostas:
Sim, mas você precisa declá-lo em readonly
vez de const
:
public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
O motivo é que const
só pode ser aplicado a um campo cujo valor é conhecido em tempo de compilação. O inicializador de matriz que você mostrou não é uma expressão constante em C #, portanto, produz um erro no compilador.
Declarar que readonly
resolve esse problema porque o valor não é inicializado até o tempo de execução (embora seja garantido que ele tenha sido inicializado antes da primeira vez que a matriz é usada).
Dependendo do que você deseja alcançar, considere também declarar uma enumeração:
public enum Titles { German, Spanish, Corrects, Wrongs };
readonly static
ter alguma semelhança com a semântica solicitada.
static
não é necessário fazê-lo funcionar, basta adicionar a possibilidade de fazer referência Titles
sem ter instância, mas remover a possibilidade de alterar o valor para diferentes instâncias (por exemplo, você pode ter um construtor com parâmetro, dependendo do valor desse readonly
campo).
Você pode declarar a matriz como readonly
, mas lembre-se de que pode alterar o elemento da readonly
matriz.
public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
...
Titles[0] = "bla";
Considere usar enum, como sugerido por Cody, ou IList.
public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
const
NÃO readonly
...
Você não pode criar uma matriz 'const' porque matrizes são objetos e só podem ser criadas em tempo de execução e entidades const são resolvidas em tempo de compilação.
O que você pode fazer é declarar sua matriz como "somente leitura". Isso tem o mesmo efeito que const, exceto que o valor pode ser definido em tempo de execução. Só pode ser definido uma vez e, posteriormente, é um valor somente leitura (ou seja, const).
const int[] a = null;
que não é muito útil, mas, na verdade, uma instância de uma constante de matriz.
Desde o C # 6, você pode escrever como:
public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" };
Veja também: C #: o C # 6.0 novo e aprimorado (especificamente o capítulo "Funções e propriedades corporativas da expressão")
Isso criará uma propriedade estática somente leitura, mas ainda permitirá que você altere o conteúdo da matriz retornada, mas quando você chamar a propriedade novamente, obterá a matriz original inalterada novamente.
Para esclarecimento, esse código é o mesmo que (ou na verdade é uma abreviação de):
public static string[] Titles
{
get { return new string[] { "German", "Spanish", "Corrects", "Wrongs" }; }
}
Observe que há uma desvantagem nessa abordagem: Na verdade, uma nova matriz é instanciada em todas as referências; portanto, se você estiver usando uma matriz muito grande, essa pode não ser a solução mais eficiente. Mas se você reutilizar a mesma matriz (colocando-a em um atributo privado, por exemplo), ela abrirá novamente a possibilidade de alterar o conteúdo da matriz.
Se você deseja ter uma matriz imutável (ou lista), também pode usar:
public static IReadOnlyList<string> Titles { get; } = new string[] { "German", "Spanish", "Corrects", "Wrongs" };
Mas isso ainda corre o risco de alterações, pois você ainda pode convertê-lo em uma string [] e alterar o conteúdo, como tal:
((string[]) Titles)[1] = "French";
Titles[0]
, por exemplo - na verdade, a tentativa de atribuição é silenciosamente ignorada. Combinado com a ineficiência de recriar a matriz sempre, pergunto-me se vale a pena mostrar essa abordagem. Por outro lado, a segunda abordagem é eficiente e você precisa se esforçar para derrotar a imutabilidade.
Se você declarar uma matriz atrás de uma interface IReadOnlyList, obterá uma matriz constante com valores constantes declarados em tempo de execução:
public readonly IReadOnlyList<string> Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" };
Disponível no .NET 4.5 e superior.
Uma solução do .NET Framework v4.5 + que aprimora a resposta do tdbeckett :
using System.Collections.ObjectModel;
// ...
public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);
Nota: Como a coleção é conceitualmente constante, pode fazer sentido static
declará-la no nível da classe .
O de cima:
Inicializa o campo implícito de apoio da propriedade uma vez com a matriz.
Observe que { get; }
- ou seja, declarar apenas um getter de propriedade - é o que torna a propriedade implicitamente somente leitura (tentar combinar readonly
com isso { get; }
é na verdade um erro de sintaxe).
Como alternativa, você pode simplesmente omitir { get; }
e adicionar readonly
para criar um campo em vez de uma propriedade, como na pergunta, mas expor membros de dados públicos como propriedades em vez de campos é um bom hábito.
Cria uma estrutura semelhante a uma matriz (permitindo acesso indexado ) que é verdadeira e robusta somente leitura (conceitualmente constante, uma vez criada), ambas com relação a:
IReadOnlyList<T>
solução, onde um (string[])
elenco pode ser usado para ganhar acesso de gravação para os elementos , como mostrado na resposta útil das mjepsen . IReadOnlyCollection<T>
interface de que, apesar da semelhança no nome para a classe ReadOnlyCollection
, nem mesmo suporta acesso indexado , tornando-o fundamentalmente inadequado para fornecer acesso semelhante a um array.)IReadOnlyCollection
não suporta acesso indexado, por isso não pode ser usado aqui. Além disso, like IReadOnlyList
(que tem acesso indexado) é suscetível à manipulação de elementos ao converter de volta para string[]
. Em outras palavras: ReadOnlyCollection
(para a qual você não pode converter uma matriz de cadeias) é a solução mais robusta. Não usar um getter é uma opção (e atualizei a resposta para observar isso), mas com dados públicos é provavelmente melhor ficar com uma propriedade.
Para minhas necessidades, defino static
array, em vez de impossível const
e funciona:
public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
const
do exemplo OP também funciona, mas isso (ou sua resposta) permite alterar: Titles
instância e qualquer valor. Então, qual é o ponto nesta resposta?
readonly
const
/ readonly
consideração, simplesmente fazê-lo funcionar (como se const
fosse um erro de sintaxe). Para algumas pessoas, parece ser uma resposta valiosa (talvez elas também tenham tentado usar const
por engano?).
Você pode adotar uma abordagem diferente: defina uma string constante para representar sua matriz e depois divida a string em uma matriz quando precisar, por exemplo
const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');
Essa abordagem fornece uma constante que pode ser armazenada na configuração e convertida em uma matriz quando necessário.
Por uma questão de completude, agora também temos o ImmutableArrays à nossa disposição. Isso deve ser verdadeiramente imutável:
public readonly static ImmutableArray<string> Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });
Requer referência System.Collections.Immutable NuGet
https://msdn.microsoft.com/en-us/library/mt452182(v=vs.111).aspx
Esta é uma maneira de fazer o que você deseja:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
public ReadOnlyCollection<string> Titles { get { return new List<string> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}
É muito semelhante a fazer uma matriz somente leitura.
public static readonly ReadOnlyCollection<String> Titles = new List<String> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
; não é necessário recriar a lista em todas as recuperações, se você a tornar uma ReadOnlyCollection de qualquer maneira.
Esta é a única resposta correta. Você não pode fazer isso no momento.
Todas as outras respostas sugerem o uso de variáveis estáticas somente leitura, que são semelhantes a , mas não iguais a uma constante. Uma constante é codificada no conjunto. Uma variável estática de somente leitura é configurável uma vez, provavelmente quando um objeto é inicializado.
Às vezes são intercambiáveis, mas nem sempre.
Como alternativa, para contornar o problema de elementos que podem ser modificados com uma matriz somente leitura, você pode usar uma propriedade estática. (Os elementos individuais ainda podem ser alterados, mas essas alterações serão feitas apenas na cópia local da matriz.)
public static string[] Titles
{
get
{
return new string[] { "German", "Spanish", "Corrects", "Wrongs"};
}
}
Obviamente, isso não será particularmente eficiente, pois uma nova matriz de strings será criada a cada vez.
Melhor alternativa:
public static readonly byte[] ZeroHash = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };