33

What is the slickest way to initialize an array of dynamic size in C# that you know of?

This is the best I could come up with

private bool[] GetPageNumbersToLink(IPagedResult result)
{
   if (result.TotalPages <= 9)
      return new bool[result.TotalPages + 1].Select(b => true).ToArray();

   ...
Ardalan Shahgholi
  • 10,987
  • 15
  • 102
  • 133
Rob
  • 1,963
  • 2
  • 20
  • 29

6 Answers6

74

If by 'slickest' you mean fastest, I'm afraid that Enumerable.Repeat may be 20x slower than a for loop. See http://dotnetperls.com/initialize-array:

Initialize with for loop:             85 ms  [much faster]
Initialize with Enumerable.Repeat:  1645 ms 

So use Dotnetguy's SetAllValues() method.

Nigel Touch
  • 1,946
  • 2
  • 19
  • 12
38

use Enumerable.Repeat

Enumerable.Repeat(true, result.TotalPages + 1).ToArray()
ebram khalil
  • 8,211
  • 7
  • 40
  • 59
Mark Cidade
  • 96,194
  • 31
  • 221
  • 232
  • 12
    I think Nigel's performance note warrants a mention - http://stackoverflow.com/questions/136836/c-array-initialization-with-non-default-value/1051227#1051227 – CrimsonX May 24 '10 at 22:47
  • 11
    I can't believe people upvote for something that's so 'fuzzy' (in my opinion) and costly for an operation as simple as filling an array. `var arr = new type[10]; for (int i = 0; i < arr.Length; i++) arr[i] = value;`, 76 characters of code that everyone understands :). Compared to 67 characters of fuzziness. – Aidiakapi Feb 09 '12 at 17:00
14

EDIT: as a commenter pointed out, my original implementation didn't work. This version works but is rather un-slick being based around a for loop.

If you're willing to create an extension method, you could try this

public static T[] SetAllValues<T>(this T[] array, T value) where T : struct
{
    for (int i = 0; i < array.Length; i++)
        array[i] = value;

    return array;
}

and then invoke it like this

bool[] tenTrueBoolsInAnArray = new bool[10].SetAllValues(true);

As an alternative, if you're happy with having a class hanging around, you could try something like this

public static class ArrayOf<T>
{
    public static T[] Create(int size, T initialValue)
    {
        T[] array = (T[])Array.CreateInstance(typeof(T), size);
        for (int i = 0; i < array.Length; i++)
            array[i] = initialValue;
        return array;
    }
}

which you can invoke like

bool[] tenTrueBoolsInAnArray = ArrayOf<bool>.Create(10, true);

Not sure which I prefer, although I do lurv extension methods lots and lots in general.

Neil Hewitt
  • 2,508
  • 18
  • 24
  • I don't believe your SetAllValues will work: In your lambda expression, x is not passed by reference, so assigning a value to it doesn't change the value stored in the array. – Samuel Jack May 06 '09 at 11:46
  • Yeah, you're absolutely right. I mentioned I hadn't actually compiled it which would have shown up that rather elementary error. I replaced the ForEach with a simple loop and that works fine, but it's not slick as the questioner demanded. – Neil Hewitt May 06 '09 at 12:53
  • 1
    Other than that, your extension method has a signature that implies that it will return a new array, but it modifies the original array and returns that instead. Bad form. – Robert Jeppesen Oct 07 '09 at 11:34
  • One, call your `SetAllValues` `Fill`, its a better name I feel. Two, take advantage of type inference of C# in your second case. So some declaration like this is possible: `ArrayEx.Create(10, true);`. – nawfal Sep 13 '13 at 05:25
  • You don't need `Array.CreateInstance`, just do `new T[]`. – Ohad Schneider Oct 09 '14 at 11:32
5

I would actually suggest this:

return Enumerable.Range(0, count).Select(x => true).ToArray();

This way you only allocate one array. This is essentially a more concise way to express:

var array = new bool[count];

for(var i = 0; i < count; i++) {
   array[i] = true;
}

return array;
Mark Cidade
  • 96,194
  • 31
  • 221
  • 232
1

Many times you'd want to initialize different cells with different values:

public static void Init<T>(this T[] arr, Func<int, T> factory)
{
    for (int i = 0; i < arr.Length; i++)
    {
        arr[i] = factory(i);
    }
}

Or in the factory flavor:

public static T[] GenerateInitializedArray<T>(int size, Func<int, T> factory)
{
    var arr = new T[size];
    for (int i = 0; i < arr.Length; i++)
    {
        arr[i] = factory(i);
    }
    return arr;
}
Ohad Schneider
  • 35,000
  • 11
  • 158
  • 195
0

Untested, but could you just do this?

return result.Select(p => true).ToArray();

Skipping the "new bool[]" part?

Mark Cidade
  • 96,194
  • 31
  • 221
  • 232
Matt Hamilton
  • 194,622
  • 60
  • 382
  • 318