Instanciation en ligne d'une liste constante

103

J'essaye de faire quelque chose comme ça:

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
        };

Mais malheureusement, cela ne fonctionne pas:

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.

Comment puis-je résoudre ce problème?

RoflcoptrException
la source
4
REMARQUE: Clôturer cette question comme un double était une erreur. La question liée concerne les tableaux de constantes , cette question concerne les listes de constantes . Bien que les deux approches fournissent à peu près la même fonctionnalité, elles sont différentes et les réponses sont différentes. Seules les réponses à cette question mentionnent ReadOnlyCollection. Les questions sont liées, mais aucune n'est en double.
Athari

Réponses:

192

constest pour les constantes de compilation. Vous pouvez simplement le faire static readonly, mais cela ne s'appliquerait qu'à la METRICSvariable elle-même (qui devrait généralement être des métriques à la place, selon les conventions de dénomination .NET ). Cela ne rendrait pas la liste immuable - pour que quelqu'un puisse appelerMETRICS.Add("shouldn't be here");

Vous voudrez peut-être utiliser un ReadOnlyCollection<T>pour l'envelopper. Par exemple:

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>encapsule juste une collection potentiellement mutable, mais comme rien d'autre n'aura accès à la List<T>suite, vous pouvez considérer la collection globale comme immuable.

(La capitalisation ici est principalement une supposition - l'utilisation de noms plus complets les rendrait plus clairs, IMO.)

Que vous déclarez comme IList<string>, IEnumerable<string>, ReadOnlyCollection<string>ou quelque chose d' autre à vous ... si vous attendez qu'il ne doit être traitée comme une séquence, puis IEnumerable<string>serait probablement plus approprié. Si l'ordre est important et que vous souhaitez que les utilisateurs puissent y accéder par index, cela IList<T>peut être approprié. Si vous voulez rendre l'immuabilité apparente, déclarez-la comme ReadOnlyCollection<T>étant pratique - mais inflexible.

Jon Skeet
la source
2
Je suis venu ici à la recherche de la new List<string>{ ... }pièce. Merci Jon :)
Jason
1
Je suppose qu'il y a une raison, mais pour moi, c'est étrange que cela ReadOnlyCollectionimplémente IList<>comme cela expose.Add
AaronLS
25

Vous devrez utiliser un static readonly liste à la place. Et si vous souhaitez que la liste soit immuable, vous pouvez envisager d'utiliser ReadOnlyCollection<T>plutôt que 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; }
}
LukeH
la source
-5

Vous recherchez un code simple, comme celui-ci:

    List<string> tagList = new List<string>(new[]
    {
         "A"
        ,"B"
        ,"C"
        ,"D"
        ,"E"
    });
Agnaldo Junior
la source
Cela ne répond pas à la question puisque l'instanciation d'une propriété est le besoin du questionneur.
vchan