Freggar
Freggar

Reputation: 1066

Where to create a "const" Array

Prenote: I know that there is no such thing as a const Array

I have an Array of Strings that are never changed in code and for now is only used in one function. I have two options to declare the Array:

  1. Make it static like so: private static readonly string[] A = { "a" ,"b", "c" }
  2. Define it inside the function as: string[] A = { "a", "b", "c" }

Which option is preferred? Is there a performance difference or other things to consider?

Upvotes: 2

Views: 3466

Answers (3)

Holger
Holger

Reputation: 2654

Although the thread is a bit old, here is a technology update:

Something like

public static ReadOnlySpan<byte> myArray => new byte[] {1, 2, 3, 4};

Is not causing any heap allocation, and the result is immutable It's kind of a compiler secret, and of course a ReadOnlySpan is not as flexible as a heap allocated array.

Upvotes: 1

Cheburek
Cheburek

Reputation: 2113

In this case you can go with any case and don't care about performance. The first option will be a bit faster on big numbers. I have executed the following code (using initialization in the method, static readonly array and hashset) with 1 and 10 mln multiple times.

class Program
{
    static void Main(string[] args)
    {
        var watch = new System.Diagnostics.Stopwatch();
        watch.Start();

        for (int i = 0; i < 10_000_000; i++)
        {
            IsSafe("POST");
        }

        watch.Stop();
        Console.WriteLine($"Execution Time: {watch.ElapsedMilliseconds} ms");
        Console.ReadLine();
    }

    //static readonly HashSet<string> safeMethods = new HashSet<string>(new[] { "GET", "OPTIONS", "HEAD", "TRACE" });
    static readonly string[] safeMethods = new[] { "GET", "OPTIONS", "HEAD", "TRACE" };
    static bool IsSafe(string method)
    {
        //var safeMethods = new[] { "GET", "OPTIONS", "HEAD", "TRACE" };
        return safeMethods.Contains(method, StringComparer.InvariantCultureIgnoreCase);
    }
}

The results on 1mln for all 3 cases are about the same - about 300ms on my laptop.

On 10mln the results are:

static array - 3.9sec
method - 4.4sec
static hashset - 4.4sec

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1501163

There's definitely a performance hit for the second option - it would create a new array and initialize it on every method call.

If you're confident that you won't accidentally mutate the array, I'd go for the first option. If you want to make it clearer in your code that you're trying to create an effectively-immutable collection, you could use:

private static readonly IReadOnlyList<string> A = new string[] { "a" ,"b", "c" };

That won't actually make it immutable though - you'd have to be careful not to pass it to any other code that might cast it back to string[] and mutate it.

For true immutability, you could use Array.AsReadOnly:

private static readonly IReadOnlyList<string> A =
    Array.AsReadOnly(new string[] { "a" ,"b", "c" });

Or of course you could use the immutable collections library.

(Note that operations via IReadOnlyList<string> will be somewhat slower than operating directly on the array; whether or not that's significant in your application will depend on what you're doing.)

Upvotes: 7

Related Questions