Встроенное создание константного списка


103

Я пытаюсь сделать что-то вроде этого:

public const List<String> METRICS = new List<String>()
        {
            SourceFile.LOC,
            SourceFile.MCCABE,
            SourceFile.NOM,
            SourceFile.NOA,
            SourceFile.FANOUT,
            SourceFile.FANIN,
            SourceFile.NOPAR,
            SourceFile.NDC,
            SourceFile.CALLS
        };

Но, к сожалению, это не работает:

FileStorer.METRICS' is of type 'System.Collections.Generic.List<string>'. A const field of a reference type other than string can only be initialized with null.

Как я могу решить эту проблему?



4
ПРИМЕЧАНИЕ. Закрытие этого вопроса как дубликата было ошибкой. Связанный вопрос касается постоянных массивов , этот вопрос касается постоянных списков . Хотя оба подхода обеспечивают примерно одинаковую функциональность, они разные, и ответы на них разные. Упоминание только ответов на этот вопрос ReadOnlyCollection. Вопросы связаны, но ни один из них не дублирует другой.
— Athari 05

Ответы:


195

constдля констант времени компиляции. Вы можете просто сделать это static readonly, но это применимо только к самой METRICSпеременной (которая обычно должна быть Метрикой, согласно соглашениям об именах .NET ). Это не сделало бы список неизменным - чтобы кто-то мог позвонитьMETRICS.Add("shouldn't be here");

Вы можете использовать a, ReadOnlyCollection<T>чтобы обернуть его. Например:

public static readonly IList<String> Metrics = new ReadOnlyCollection<string>
    (new List<String> { 
         SourceFile.LoC, SourceFile.McCabe, SourceFile.NoM,
         SourceFile.NoA, SourceFile.FanOut, SourceFile.FanIn, 
         SourceFile.Par, SourceFile.Ndc, SourceFile.Calls });

ReadOnlyCollection<T>просто обертывает потенциально изменяемую коллекцию, но поскольку ничто другое не будет иметь доступа к ней List<T>впоследствии, вы можете рассматривать всю коллекцию как неизменяемую.

(Использование заглавных букв здесь в основном предположение - использование более полных имен сделает их более понятными, ИМО.)

Если вы объявляете его как IList<string>, IEnumerable<string>, ReadOnlyCollection<string>или что - то еще до вас ... если вы ожидаете , что она должна рассматриваться только как последовательность, то IEnumerable<string>, вероятно , будет наиболее подходящим. Если порядок имеет значение и вы хотите, чтобы люди могли получить к нему доступ по индексу, это IList<T>может быть целесообразным. Если вы хотите сделать неизменность очевидной, объявите это как ReadOnlyCollection<T>можно удобно, но негибко.


2
Я пришел сюда в поисках new List<string>{ ... }запчастей. Спасибо, Джон :)
— Джейсон

1
Я полагаю, что есть причина, но для меня это странно, что ReadOnlyCollectionинструменты, IList<>как это раскрывает.Add
— AaronLS

25

static readonlyВместо этого вам нужно будет использовать список. И если вы хотите, чтобы список был неизменным, вы можете подумать об использовании ReadOnlyCollection<T>вместо List<T>.

private static readonly ReadOnlyCollection<string> _metrics =
    new ReadOnlyCollection<string>(new[]
        {
            SourceFile.LOC,
            SourceFile.MCCABE,
            SourceFile.NOM,
            SourceFile.NOA,
            SourceFile.FANOUT,
            SourceFile.FANIN,
            SourceFile.NOPAR,
            SourceFile.NDC,
            SourceFile.CALLS
        });

public static ReadOnlyCollection<string> Metrics
{
    get { return _metrics; }
}

-5

Вам нужен простой код, например:

    List<string> tagList = new List<string>(new[]
    {
         "A"
        ,"B"
        ,"C"
        ,"D"
        ,"E"
    });

Это не дает ответа на вопрос, поскольку создание экземпляра свойства является потребностью запрашивающего.
— vchan
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.