Можно ли написать что-то похожее на следующее?Объявить массив const
public const string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
Можно ли написать что-то похожее на следующее?Объявить массив const
public const string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
Да, но вы должны объявить его readonly
вместо const
:
public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
Причина заключается в том, что const
может быть применен только к области, значение которого известно во время компиляции. Инициализатор массива, который вы указали, не является постоянным выражением в C#, поэтому он создает ошибку компилятора.
Объявление readonly
решает эту проблему, потому что значение не инициализируется до времени выполнения (хотя гарантировано, что оно будет инициализировано до первого использования массива).
В зависимости от того, что это такое, что вы в конечном итоге хотите достичь, вы можете также рассмотреть вопрос об объявлении перечисление:
public enum Titles { German, Spanish, Corrects, Wrongs };
Я считаю, что вы можете сделать это только для чтения.
Массивы, вероятно, являются одной из тех вещей, которые могут быть оценены только при времени выполнения. Константы должны оцениваться во время компиляции. Попробуйте использовать «readonly» вместо «const».
Вы не можете создать «» константный массив, потому что массивы являются объектами и могут быть только созданные во время выполнения, и объекты const разрешаются во время компиляции.
Вместо этого вы должны объявить свой массив как «readonly». У этого есть тот же эффект, что и const, за исключением того, что значение может быть установлено во время выполнения. Это может быть только , установленное один раз, и после этого оно имеет значение readonly (т.е. const).
Вы можете объявить массив как 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();
В .NET 4.5 и выше вы можете объявить список как IReadOnlyList
Для моих потребностей я определяю static
массив, вместо того, чтобы невозможно const
и она работает: public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
Простое удаление 'const' из примера OP также работает, но это (или ваш ответ) позволяет изменить оба: экземпляр' Titles' и любое значение. Так в чем смысл этого ответа? – Sinatr
@ Синат, я ответил на это 3 года назад, когда я перешел работать на C#. Я оставил его, теперь я в мире Java. Возможно, я забыл добавить 'readonly' – ALZ
. После второй мысли ваш ответ является прямым * как заставить OP-код работать * без каких-либо' const'/'readonly' соображений, просто * делая его работу * (например, если' const' была синтаксической ошибкой). Для некоторых людей это кажется * ценным * ответом (возможно, они также пытались использовать ['const'] (https://msdn.microsoft.com/en-us/library/e6w8fe1b.aspx) по ошибке?). – Sinatr
Вы можете использовать другой подход: определить постоянную строку, чтобы представить свой массив, а затем разбить строку в массив, когда вам это нужно, например
const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');
Этот подход дает вам константу, которая может быть сохранена в конфигурации и преобразована в массив при необходимости.
Аластер
Это способ сделать то, что вы хотите:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
public ReadOnlyCollection<string> Titles { get { return new List<string> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}
Он очень похож делать только для чтения массива.
Вы можете просто сделать это как «public static readonly ReadOnlyCollection
В качестве альтернативы, чтобы обойти проблему, связанную с элементами, с помощью массива readonly, вместо этого вы можете использовать статическое свойство. (Отдельные элементы еще можно изменить, но эти изменения будут сделаны только на локальной копии массива.)
public static string[] Titles
{
get
{
return new string[] { "German", "Spanish", "Corrects", "Wrongs"};
}
}
Конечно, это не будет особенно эффективным, как новый массив строк создается каждый раз, ,
Поскольку C# 6 вы можете написать это нравится:
public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" };
Смотрите также: C# : The New and Improved C# 6.0 (в частности, главы "Expression работоспособной Функции и свойство")
Это делает только для чтения свойства статично, но он все равно позволит вам изменить содержимое возвращаемого массива, но когда вы снова вызовете свойство, вы снова получите исходный неизменный массив.
Для уточнения, этот код так же, как (или на самом деле сокращенная запись):
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";
Какова прибыль использования объекта вместо поля в этом случае? –
Поле не может вернуть новый объект для каждого вызова. Свойство - это своего рода «скрытая функция». – mjepson
Если вы имели в виду последний вариант, это можно сделать, используя как поле, так и свойство, но, поскольку оно является общедоступным, я предпочитаю Свойство. Я никогда не пользуюсь публичным полем с момента введения свойств. – mjepson
.NET Framework v4.5 + решения, что улучшает tdbeckett's answer:
using System.Collections.ObjectModel;
// ...
public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);
Примечание: учитывая, что коллекция концептуально постоянна, имеет смысл сделать это static
, чтобы объявить ее на уровне класса.
выше:
Инициализирует неявное поле подложки отеля раз с массивом.
Обратите внимание, что { get; }
- то есть, объявляя только свойство поглотитель - это то, что делает сам неявно свойство только для чтения (пытаясь объединить readonly
с { get; }
на самом деле ошибка синтаксиса).
В качестве альтернативы, вы можете просто опустить { get; }
и добавить readonly
создать поле вместо свойства, как и в вопросе, но подвергая общественные элементы данных как свойства, а не полей является хорошей привычкой, чтобы сформировать ,
Создает массив структуру, подобную (с учетом индексированного доступа), который действительно и решительно только для чтения (концептуально, постоянная, после создания), как в отношении:
IReadOnlyList<T>
раствора, где (string[])
бросок может быть использован, чтобы получить доступ на запись к элементам, как показано на mjepsen's helpful answerIReadOnlyCollection<T>
,. который, несмотря на свое название, сходство с классReadOnlyCollection
, даже не поддерживает с индексом, что делает его принципиально непригодным для обеспечения доступа к массиву).@mortb: К сожалению, 'IReadOnlyCollection' не поддерживает индексированный доступ, поэтому его здесь нельзя использовать. Кроме того, как 'IReadOnlyList' (который имеет индексированный доступ), он подвержен обработке элементов, возвращаясь к' string [] '. Другими словами: 'ReadOnlyCollection' (который вы не можете отличить строковый массив) является наиболее надежным решением. Не использовать геттер - это вариант (и я обновил ответ, чтобы отметить это), но с данными _public_, вероятно, лучше придерживаться свойства. – mklement0
@mortb: P.S .: Я также обновил ответ, чтобы показать, почему 'IReadOnlyCollection' не является вариантом. – mklement0
Если вы объявляете массив за интерфейс IReadOnlyList вы получаете постоянный массив с постоянными значениями, объявленный во время выполнения:
public readonly IReadOnlyList<string> Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" };
Доступен в .NET 4.5 и выше.
статические могут быть использованы, public static string [] Titles = new string [] {"German", "Spanish"}; –