Declare a const array

495,072

Solution 1

Yes, but you need to declare it readonly instead of const:

public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };

The reason is that const can only be applied to a field whose value is known at compile-time. The array initializer you've shown is not a constant expression in C#, so it produces a compiler error.

Declaring it readonly solves that problem because the value is not initialized until run-time (although it's guaranteed to have initialized before the first time that the array is used).

Depending on what it is that you ultimately want to achieve, you might also consider declaring an enum:

public enum Titles { German, Spanish, Corrects, Wrongs };

Solution 2

You can't create a 'const' array because arrays are objects and can only be created at runtime and const entities are resolved at compile time.

What you can do instead is to declare your array as "readonly". This has the same effect as const except the value can be set at runtime. It can only be set once and it is thereafter a readonly (i.e. const) value.

Solution 3

You can declare array as readonly, but keep in mind that you can change element of readonly array.

public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
...
Titles[0] = "bla";

Consider using enum, as Cody suggested, or IList.

public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();

Solution 4

This is the only correct answer. You cannot currently do this.

All the other answers are suggesting using static read-only variables which are similar to, but not the same as a constant. A constant is hard coded into the assembly. A static read only variable is settable once, probably as an object is is initialized.

These are sometimes interchangeable, but not always.

EDIT: I thought I'd throw this in, as it seem like the person who asked the question was a little fuzzy about arrays. When you declare an array, it is a pointer to a segment of memory that contains the array. It is very simple in that it is just an address, with no complex logic controlling if it is readable or writable. It gives you a pointer, and you can do whatever you want with it.

This is part of the reason why it is a little tricky to make an immutable array. You could write a class that wraps the array and only allows reading of it by returning a copy, but then it really isn't just an array anymore, it is an object that wraps an array.

Some people have suggested using static, or readonly to simulate the behavior you would see if you could create const array. These have some side effects that might not be obvious to the casual reader.

To truly get a const array, there would need to be an update to C# and the MSIL underlying code to allow reading from an array, but no writing.

Solution 5

Since C# 6 you can write it like:

public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" };

See also: C# : The New and Improved C# 6.0 (specifically the chapter "Expression Bodied Functions and Properties")

This will make a read-only static property, but it will still allow you to alter the content of the array returned, but when you call the property again, you will get the original, unaltered array again.

For clarification, this code is the same as (or actually a shorthand for):

public static string[] Titles
{
    get { return new string[] { "German", "Spanish", "Corrects", "Wrongs" }; }
}

Please note that there is a downside to this approach: A new array is actually instantiated on each and every reference, so if you are using a very large array, this might not be the most efficient solution. But if you re-use the same array (by putting it in a private attribute for instance) it will again open up the possibility to change the contents of the array.

If you want to have an immutable array (or list) you could also use:

public static IReadOnlyList<string> Titles { get; } = new string[] { "German", "Spanish", "Corrects", "Wrongs" };

But, this still has a risk for changes, as you can still cast it back to a string[] and alter the contents, as such:

((string[]) Titles)[1] = "French";
Share:
495,072
Jaime Oro
Author by

Jaime Oro

Industrial Engineer learning C# and using stackoverflow for that purpose.

Updated on November 16, 2021

Comments

  • Jaime Oro
    Jaime Oro over 2 years

    Is it possible to write something similar to the following?

    public const string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
    
  • Marc Gravell
    Marc Gravell over 13 years
    Note that the array here isn't readonly, of course; Titles[2]="Welsh"; would work just fine at runtime
  • tymtam
    tymtam over 11 years
    You probably want it static too
  • serhio
    serhio over 10 years
    how about declaring a "const" array in a method body, not in the class one?
  • Grzegorz Smulko
    Grzegorz Smulko almost 10 years
    In .NET 4.5 and higher you can declare a list as IReadOnlyList<string> instead of IList<string>.
  • John Suit
    John Suit over 9 years
    This won't help when you ABSOLUTELY need a const, such as with switch statement cases.
  • Anton
    Anton over 9 years
    Sorry for the down vote, but const also implies static. Declaring the array as read only is not close to a workaround. it needs to be readonly static to have any resemblance of the requested semantics.
  • Rodrigo López
    Rodrigo López about 9 years
    and const is only for primitive types
  • jocull
    jocull almost 9 years
    Why can you declare a string as const if a string is just a char[]?
  • Nyerguds
    Nyerguds almost 9 years
    You can just do that as public static readonly ReadOnlyCollection<String> Titles = new List<String> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();; no need to recreate the list on every retrieve if you make it a ReadOnlyCollection anyway.
  • Niall Connaughton
    Niall Connaughton almost 9 years
    string isn't a char[], see the source. Strings can be consts in C# because the compiler will replace all references to the const with the actual string literal itself.
  • Radderz
    Radderz over 8 years
    I think the cost of performing the split far outstrips any benefits made by defining const. But +1 for a unique approach and thinking outside the box! ;)
  • Cody Gray
    Cody Gray over 8 years
    I thought the static part was obvious on its own, and not an integral part of the solution. I suppose it isn't to everyone else who visits this answer; it is sure a popular one. It certainly doesn't hurt to have it there. Wonder why someone hasn't edited it in already...
  • Sinatr
    Sinatr over 8 years
    Simply removing const from OP example also works, but that (or your answer) allows to change both: Titles instance and any value. So what is the point in this answer?
  • Sinatr
    Sinatr over 8 years
    @Anton, have you and your "followers" removed downvote? To me static is not required to make it working, it just add possibility to reference Titles without having instance, but remove possibility to change value for different instances (e.g. you can have constructor with parameter depending on which you change value of that readonly field).
  • ALZ
    ALZ over 8 years
    @Sinatr, I answered this 3 years ago, when I strted working in C#. I left it, now I'm in Java world. Perhaps I forgot to add readonly
  • Sinatr
    Sinatr about 8 years
    After second thought, your answer is a direct how to make OP code working, without any const/readonly considerations, simply making it working (like if const was a syntax mistake). For some people it seems to be a valuable answer (perhaps they also tried to use const by mistake?).
  • nicolas2008
    nicolas2008 over 7 years
    What is the profit of using property instead of field in this case?
  • mjepson
    mjepson over 7 years
    A field cannot return a new object on each call. A property is basically a sort of "function in disguise".
  • mjepson
    mjepson over 7 years
    If you were referring to the last option, that can be done using both a field or a property, but since it is public, I prefer a Property. I never use a public field since the introduction of Properties.
  • mklement0
    mklement0 about 7 years
    There is another downside to the 1st approach: you won't get a compilation error if you assign to Titles[0], for instance - in effect, the assignment attempt is quietly ignored. Combined with the inefficiency of recreating the array every time, I wonder if this approach is even worth showing. By contrast, the 2nd approach is efficient, and you have to go out of your way to defeat the immutability.
  • mklement0
    mklement0 about 7 years
    @mortb: Unfortunately, IReadOnlyCollection doesn't support indexed access, so it can't be used here. Additionally, like IReadOnlyList (which does have indexed access) it is susceptible to element manipulation by casting back to string[]. In other words: ReadOnlyCollection (which you cannot cast a string array to) is the most robust solution. Not using a getter is an option (and I've updated the answer to note that), but with public data it's probably better to stick with a property.
  • Kalpesh Popat
    Kalpesh Popat over 5 years
    I was about to post the same solution and then saw this, contrary to the harsh and negative remarks, this was actually perfect for my scenario, where i needed to pass a const to an Attribute, and then i split the value in attribute constructor to get what i needed. and i see no reason why it will have performance cost since attributes are not created for each instance.
  • Radderz
    Radderz about 5 years
    This post highlights why arrays cannot be declared as constants
  • waldrumpus
    waldrumpus almost 5 years
    It is possible to declare a constant array; the problem is initializing it with a constant value. The only working example that comes to mind is const int[] a = null; which is not very useful, but indeed an instance of an array constant.
  • KevinVictor
    KevinVictor about 4 years
    Just to be clear, you can still change the values in an IReadOnlyList (just not add or remove elements). But yes, declaring it as an IReadOnlyList would be better than an IList.
  • ElectricErger
    ElectricErger over 2 years
    Thank you. I was wondering why the most upvoted solutions weren't working for default parameters.