Подтвердить что ты не робот

Инициализация многомерного массива Const

Почему выполняется следующее?

class A
{
    public int[,] i = { { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 } };

    static void Main(string[] args)
    {
    }
}

В то время как следующее не?

class A
{
    public const int[,] i = { { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 } };

    static void Main(string[] args)
    {
    }
}

Не допускается, чтобы для ссылочного типа const, отличного от строки, назначалось что-либо, кроме нуля. Поскольку это массив (ссылка), ему должно быть присвоено значение null (?). Как он будет инициализироваться, если он будет постоянным и нулевым?

4b9b3361

Ответ 1

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

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

EDIT:

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

public static int[,] i = { { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 } };
       ^ Static Keyword

Вы можете получить доступ к нему как (если он еще находится в class A):

A.i[0, 1]

Я надеюсь, что это поможет вам

Чтобы узнать больше, посмотрите MSDN: http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k(CS0134);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5)&rd=true

EDITEDIT: Если вам нужно приклеить статическую таблицу к коду и никогда не позволять кому-либо изменять ее после ее инициализации, для этого нужно ключевое слово readonly:

public static readonly int[,] i = { { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 } };
       ^ Static ^Readonly Keywords

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

Ответ 2

Это не работает, потому что ограничение на ключевое слово const.

Из MSDN:

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

Постоянное выражение - это выражение, которое может быть полностью оценено во время компиляции. Поэтому единственными возможными значениями констант ссылочных типов являются строка и нуль

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

Ответ 3

Константы оцениваются во время компиляции. Массив - это ссылочные типы, и единственный способ создать ссылочный тип - использовать ключевое слово new (которое неявно в вашем коде).

new не может использоваться в постоянном выражении, потому что его невозможно оценить во время компиляции.

См. MSDN: http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k(CS0134);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5)&rd=true