Is it possible to write something similar to the following?
public const string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
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 };
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();
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.
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";
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.
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.
A .NET Framework v4.5+ solution that improves on tdbeckett's answer:
using System.Collections.ObjectModel;
// ...
public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);
Note: Given that the collection is conceptually constant, it may make sense to make it static
to declare it at the class level.
The above:
Initializes the property's implicit backing field once with the array.
Note that { get; }
- i.e., declaring only a property getter - is what makes the property itself implicitly read-only (trying to combine readonly
with { get; }
is actually a syntax error).
Alternatively, you could just omit the { get; }
and add readonly
to create a field instead of a property, as in the question, but exposing public data members as properties rather than fields is a good habit to form.
Creates an array-like structure (allowing indexed access) that is truly and robustly read-only (conceptually constant, once created), both with respect to:
IReadOnlyList<T>
solution, where a (string[])
cast can be used to gain write access to the elements, as shown in mjepsen's helpful answer.IReadOnlyCollection<T>
interface, which, despite the similarity in name to class ReadOnlyCollection
, does not even support indexed access, making it fundamentally unsuitable for providing array-like access.)You could take a different approach: define a constant string to represent your array and then split the string into an array when you need it, e.g.
const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');
This approach gives you a constant which can be stored in configuration and converted to an array when needed.
For the sake of completeness, now we also have ImmutableArrays at our disposal. This should be truly immutable:
public readonly static ImmutableArray<string> Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });
Requires System.Collections.Immutable NuGet reference
https://msdn.microsoft.com/en-us/library/mt452182(v=vs.111).aspx
This is a way to do what you want:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
public ReadOnlyCollection<string> Titles { get { return new List<string> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}
It is very similar to doing a readonly array.
As an alternative, to get around the elements-can-be-modified issue with a readonly array, you can use a static property instead. (The individual elements can still be changed, but these changes will only be made on the local copy of the array.)
public static string[] Titles
{
get
{
return new string[] { "German", "Spanish", "Corrects", "Wrongs"};
}
}
Of course, this will not be particularly efficient as a new string array is created each time.