Inline Constant List Instance

I am trying to do something like this:

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

But unfortunately this does not work:

 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. 

How can I solve this problem?

+81
c #
Jan 12 '11 at 11:44
source share
4 answers

const - for compile-time constants. You could just do it static readonly , but this only applies to the METRICS variable METRICS (which usually should be a metric METRICS NET naming convention ). This will not make the list immutable - so someone might call METRICS.Add("shouldn't be here");

You can use ReadOnlyCollection<T> to wrap it. For example:

 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> simply wraps the potentially mutable collection, but since nothing else will have access to the List<T> afterwards, you can consider the general collection immutable.

(Capitalization here is mostly speculation - using more complete names will make them clearer, IMO.)

Whether you IList<string> it as IList<string> , IEnumerable<string> , ReadOnlyCollection<string> or something else up to you ... if you expect it to be considered only as a sequence, then IEnumerable<string> will probably be more suitable. If order matters, and you want people to be able to access it by index, IList<T> may be appropriate. If you want to make immutability obvious, declaring it as ReadOnlyCollection<T> can be convenient, but inflexible.

+160
Jan 12 2018-11-11T00:
source share

Instead, you will need to use the static readonly list. And if you want the list to be immutable, you may need to use ReadOnlyCollection<T> rather than 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; } } 
+21
Jan 12 '11 at 11:45
source share

.NET supports truly immutable collections, read-only views of mutable collections, and read-only interfaces implemented by a mutable collection .

One such immutable collection is ImmutableArray <>, which you can create as a.ToImmutableArray () in your example. Be sure to check out the other MSDN list options because you might be better served by another immutable collection. If you want to make copies of the original sequence with minor changes, ImmutableList <> can be, for example, faster (although it is cheaper to create an array and access it). Please note that a.Add (...); valid but returns a new collection instead of changing. If you have a resharper, this will warn you if you ignore the return value of a clean method such as Add (and there might be a roslyn extension to do something like this that I don't know about). If you go this way, consider skipping List <> completely and moving directly to immutable collections.

Read-only mutable collection views are slightly less secure, but are supported in older versions of .NET. The type of packaging is called ReadOnlyCollection <>, which in your example you can create as a.AsReadOnly (). This collection does not guarantee immutability; it only ensures that you cannot change it. Some other piece of code that shares a link to the underlying List <> can still change it. In addition, ReadOnlyCollection also incurs some additional overhead; therefore, you may not win much by avoiding immutable collections for performance reasons (TODO: compare this statement). You can use a read-only shell like this one even in the public API - there is no way (without reflection) to get a basic list. However, since it is often not faster than immutable collections, and it is also not entirely safe, I recommend avoiding ReadOnlyCollection <> - I never use it personally again.

Read-only interfaces implemented by mutable collections are even lower on the security scale, but fast. You can simply cast List <> as IReadOnlyList <>, which you can do in your example as IReadOnlyList lst = a. These are my preferences in the internal code - you still get static type safety, you are simply not protected from malicious code or code that uses type checks and unreasonably performs type casting (but this can be avoided by using code checks in my experience). I have never been bitten by this choice, but it is less secure than the two options above. On the other hand, it does not incur any costs and works faster. If you usually do this, you might want to define an extension method that will perform the conversion for you (a cast may not be safe in C #, because they not only perform a safe conversion, but they may refuse to downgrade, and user-defined conversions - so it's a good idea to avoid explicit casts wherever possible).

Please note that in all cases only the sequence itself is read-only. Basic objects are not affected (for example, int or string are immutable, but more complex objects may or may not be).

+1
Jan 08 '18 at 13:12
source share

You are looking for simple code, for example:

  List<string> tagList = new List<string>(new[] { "A" ,"B" ,"C" ,"D" ,"E" }); 
0
Mar 28 '19 at 14:43
source share



All Articles