Объявить массив как const


можно ли написать что-нибудь подобное?

public const string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
13 323

13 ответов:

да, но вы должны объявить его readonly вместо const:

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

причина в том, что const могут быть применены только к полю, значение которого известно во время компиляции. Инициализатор массива, который вы показали, не является постоянным выражением В C#, поэтому он создает ошибку компилятора.

объявив его readonly решает эту проблему, потому что значение не инициализируется до времени выполнения (хотя гарантируется, что оно инициализировалось до первого раза, когда массив используемый.)

в зависимости от того, что вы в конечном итоге хотите достичь, вы также можете рассмотреть возможность объявления перечисления:

public enum Titles { German, Spanish, Corrects, Wrongs };

вы можете объявить массив как readonly, но имейте в виду, что вы можете изменить элемент readonly массив.

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

рассмотрите возможность использования перечисления, как предложил Коди, или IList.

public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();

вы не можете создать массив 'const', потому что массивы являются объектами и могут быть только созданные во время выполнения и const сущности разрешаются во время компиляции.

вместо этого вы можете объявить свой массив как "только для чтения". Это такой же эффект как const, за исключением стоимости может быть установлена во время выполнения. Это может быть только после установки и после чтения (т. е. const) значение.

вы можете использовать другой подход: определить постоянную строку для представления вашего массива, а затем разделить строку на массив, когда вам это нужно, например

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

этот подход дает вам константу, которая может быть сохранена в конфигурации и преобразована в массив, когда это необходимо.

Аластер

для моих нужд я определяю static массив, а не невозможно const и все работает: public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };

С C# 6 Вы можете написать его так:

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

Читайте также: C#: новый и улучшенный C# 6.0 (в частности, глава "выражение телесных функций и свойств")

это сделает статическое свойство только для чтения, но оно все равно позволит вам изменить содержимое возвращаемого массива, но при повторном вызове свойства вы снова получите исходный неизмененный массив.

для уточнения, этот код такой же как (или фактически a сокращенно):

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

обратите внимание, что у этого подхода есть недостаток: новый массив фактически создается для каждой ссылки, поэтому, если вы используете очень большой массив, это может быть не самым эффективным решением. Но если вы повторно используете тот же массив (например, поместив его в частный атрибут), он снова откроет возможность изменить содержимое массива.

если вы хотите иметь неизменяемый массив (или список) можно также использование:

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

но, это все еще имеет риск для изменений, так как вы все еще можете вернуть его в строку[] и изменить содержимое, как таковое:

((string[]) Titles)[1] = "French";

Это способ сделать то, что вы хотите:

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

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

это очень похоже на выполнение массива только для чтения.

на .Чистый рамках В4.5+ Решение это улучшает ответ tdbeckett:

using System.Collections.ObjectModel;

// ...

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

Примечание: учитывая, что коллекция концептуально постоянна, это может иметь смысл сделать его static объявить его в класс

Если вы объявляете массив за интерфейсом IReadOnlyList, вы получаете постоянный массив с постоянными значениями, который объявляется во время выполнения:

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

доступно в .NET 4.5 и выше.

Я считаю, что вы можете сделать это только для чтения.

массивы, вероятно, одна из тех вещей, которые могут быть оценены только на во время выполнения. Константы должны быть вычислены во время компиляции. Попробуйте использовать "только для чтения" вместо "const".

в качестве альтернативы, чтобы обойти проблему elements-can-be-modified с массивом только для чтения, вы можете использовать статическое свойство вместо этого. (Отдельные элементы все еще могут быть изменены, но эти изменения будут сделаны только в локальной копии массива.)

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

конечно, это не будет особенно эффективно, так как каждый раз создается новый массив строк.

для полноты картины, теперь у нас в распоряжении также есть неизменные лучи. Это должно быть действительно неизменным:

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

Требует Система.Коллекции.Неизменяемая ссылка NuGet

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