158

How to add new item in existing string array in C#.net?

I need to preserve the existing data.

19 Answers 19

128

I would use a List if you need a dynamically sized array:

List<string> ls = new List<string>();
ls.Add("Hello");
Sign up to request clarification or add additional context in comments.

10 Comments

And if required, do ls.ToArray() at the end
Using another mechanic than asked in the question is not an answer.
@EdS.The question was, how to add an item to an existing string array, but this answer has no array at all, instead it creates a new List<>. In my application, I can't change the type to List<>, therefore I have to resize an array (making a copy...). The answer by Ali Ersöz helped me.
Why in the world would you? If you had to, I'd suggest Concat()
Agree with @user11909 you're answering a different question than what was asked. You may think you're helping to teach an inexperienced programmer about an alternative he didn't consider but what you're actually doing is slowing people down who are specifically looking into adding to arrays. This should have been a comment. Ali Ersöz's answer is much better.
|
116

That could be a solution;

Array.Resize(ref array, newsize);
array[newsize - 1] = "newvalue"

But for dynamic sized array I would prefer list too.

2 Comments

this is not suitable for more than a few time invoking. because the 'Resize' function have a huge performance. bug for one or two time, this is very good.
@ad Don't preoptimize. This is perfectly suitable unless benchmarks in whatever context in which it's used determine it isn't.
55

Using LINQ:

arr = (arr ?? Enumerable.Empty<string>()).Concat(new[] { newitem }).ToArray();

I like using this as it is a one-liner and very convenient to embed in a switch statement, a simple if-statement, or pass as argument.

EDIT:

Some people don't like new[] { newitem } because it creates a small, one-item, temporary array. Here is a version using Enumerable.Repeat that does not require creating any object (at least not on the surface -- .NET iterators probably create a bunch of state machine objects under the table).

arr = (arr ?? Enumerable.Empty<string>()).Concat(Enumerable.Repeat(newitem,1)).ToArray();

And if you are sure that the array is never null to start with, you can simplify it to:

arr.Concat(Enumerable.Repeat(newitem,1)).ToArray();

Notice that if you want to add items to a an ordered collection, List is probably the data structure you want, not an array to start with.

2 Comments

Very nice +1. I have similar code as a generic extension method. I've included the code in this answer: stackoverflow.com/a/11035286/673545
This is very useful found it whilst searching for "how to append to an array in one line of code in c#" - hopefully this comment is enough to find it again next time.
37

Very old question, but still wanted to add this.

If you're looking for a one-liner, you can use the code below. It combines the list constructor that accepts an enumerable and the "new" (since question raised) initializer syntax.

myArray = new List<string>(myArray) { "add this" }.ToArray();

Comments

31

Arrays in C# are immutable, e.g. string[], int[]. That means you can't resize them. You need to create a brand new array.

Here is the code for Array.Resize:

public static void Resize<T>(ref T[] array, int newSize)
{
    if (newSize < 0)
    {
        throw new ArgumentOutOfRangeException("newSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
    }
    T[] sourceArray = array;
    if (sourceArray == null)
    {
        array = new T[newSize];
    }
    else if (sourceArray.Length != newSize)
    {
        T[] destinationArray = new T[newSize];
        Copy(sourceArray, 0, destinationArray, 0, (sourceArray.Length > newSize) ? newSize : sourceArray.Length);
        array = destinationArray;
    }
}

As you can see it creates a new array with the new size, copies the content of the source array and sets the reference to the new array. The hint for this is the ref keyword for the first parameter.

There are lists that can dynamically allocate new slots for new items. This is e.g. List<T>. These contain immutable arrays and resize them when needed (List<T> is not a linked list implementation!). ArrayList is the same thing without Generics (with Object array).

LinkedList<T> is a real linked list implementation. Unfortunately you can add just LinkListNode<T> elements to the list, so you must wrap your own list elements into this node type. I think its use is uncommon.

3 Comments

I think you have meant Array.Copy
Only answer that provides some information for why it is not possible and does not just suggest to use a list...
I believe Aray.Resize can resize an array without losing its contents. learn.microsoft.com/en-us/dotnet/api/…
28
 Array.Resize(ref youur_array_name, your_array_name.Length + 1);
 your_array_name[your_array_name.Length - 1] = "new item";

Comments

13

A new Append<TSource> method has been added to IEnumerable<TSource> since .NET Framework 4.7.1 and .NET Core 1.0.

Here is how to use it:

var numbers = new [] { "one", "two", "three" };
numbers = numbers.Append("four").ToArray();
Console.WriteLine(string.Join(", ", numbers)); // one, two, three, four

Note that if you want to add the element at the beginning of the array, you can use the new Prepend<TSource> method instead.

1 Comment

can this be used with a null or empty array? how?
8

You can expand on the answer provided by @Stephen Chung by using his LINQ based logic to create an extension method using a generic type.

public static class CollectionHelper
{
    public static IEnumerable<T> Add<T>(this IEnumerable<T> sequence, T item)
    {
        return (sequence ?? Enumerable.Empty<T>()).Concat(new[] { item });
    }

    public static T[] AddRangeToArray<T>(this T[] sequence, T[] items)
    {
        return (sequence ?? Enumerable.Empty<T>()).Concat(items).ToArray();
    }

    public static T[] AddToArray<T>(this T[] sequence, T item)
    {
        return Add(sequence, item).ToArray();
    }

}

You can then call it directly on the array like this.

    public void AddToArray(string[] options)
    {
        // Add one item
        options = options.AddToArray("New Item");

        // Add a 
        options = options.AddRangeToArray(new string[] { "one", "two", "three" });

        // Do stuff...
    }

Admittedly, the AddRangeToArray() method seems a bit overkill since you have the same functionality with Concat() but this way the end code can "work" with the array directly as opposed to this:

options = options.Concat(new string[] { "one", "two", "three" }).ToArray();

2 Comments

Thank you, This was very helpful, I have added an option to remove an item (I hope that this is OK with you).
@TalSegal you are welcome, my pleasure. Use the code as you see fit!
8

So if you have a existing array, my quick fix will be

var tempList = originalArray.ToList();
tempList.Add(newitem);

Now just replace the original array with the new one

originalArray = tempList.ToArray();

Comments

7

It's better to keeps Array immutable and fixed size.

you can simulate Add by Extension Method and IEnumerable.Concat()

public static class ArrayExtensions
    {
        public static string[] Add(this string[] array, string item)
        {
            return array.Concat(new[] {item}).ToArray();
        }
    }

Comments

6

if you are working a lot with arrays and not lists for some reason, this generic typed return generic method Add might help

    public static T[] Add<T>(T[] array, T item)
    {
        T[] returnarray = new T[array.Length + 1];
        for (int i = 0; i < array.Length; i++)
        {
            returnarray[i] = array[i];
        }
        returnarray[array.Length] = item;
        return returnarray;
    }

Comments

6

All proposed answers do the same as what they say they'd like to avoid, creating a new array and adding a new entry in it only with lost more overhead. LINQ is not magic, list of T is an array with a buffer space with some extra space as to avoid resizing the inner array when items are added.

All the abstractions have to solve the same issue, create an array with no empty slots that hold all values and return them.

If you need the flexibility an can create a large enough list that you can use to pass then do that. else use an array and share that thread-safe object. Also, the new Span helps to share data without having to copy the lists around.

To answer the question:

Array.Resize(ref myArray, myArray.Length + 1);
data[myArray.Length - 1] = Value;

Comments

3

Using a list would be your best option for memory management.

Comments

2
string str = "string ";
List<string> li_str = new List<string>();
    for (int k = 0; k < 100; i++ )
         li_str.Add(str+k.ToString());
string[] arr_str = li_str.ToArray();

Comments

2

What about using an extension method? For instance:

public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> source, TSource item)
{
    return source.Union(new TSource[] { item });
}

for instance:

string[] sourceArray = new []
{
    "foo",
    "bar"
}
string additionalItem = "foobar";
string result = sourceArray.Union(additionalItem);

Note this mimics this behavior of Linq's Uniion extension (used to combine two arrays into a new one), and required the Linq library to function.

Comments

1

I agree with Ed. C# does not make this easy the way VB does with ReDim Preserve. Without a collection, you'll have to copy the array into a larger one.

2 Comments

Thank God! ReDim is incredibly slow when abused. =)
ReDim Preserve simply copies the array into a lager one. There is no miraculous array resizing.
0
private static string[] GetMergedArray(string[] originalArray, string[] newArray)
    {
        int startIndexForNewArray = originalArray.Length;
        Array.Resize<string>(ref originalArray, originalArray.Length + newArray.Length);
        newArray.CopyTo(originalArray, startIndexForNewArray);
        return originalArray;
    }

Comments

0

Why not try out using the Stringbuilder class. It has methods such as .insert and .append. You can read more about it here: http://msdn.microsoft.com/en-us/library/2839d5h5(v=vs.71).aspx

Comments

-1

Since this question not satisfied with provided answer, I would like to add this answer :)

public class CustomArrayList<T> 
 {  
   private T[] arr;  private int count;  

public int Count  
  {   
    get   
      {    
        return this.count;   
      }  
   }  
 private const int INITIAL_CAPACITY = 4;  

 public CustomArrayList(int capacity = INITIAL_CAPACITY) 
 {  
    this.arr = new T[capacity];   this.count = 0; 
  } 

 public void Add(T item) 
  {  
    GrowIfArrIsFull();  
   this.arr[this.count] = item;  this.count++; 
  }  

public void Insert(int index, T item) 
{  
 if (index > this.count || index < 0)  
    {   
      throw new IndexOutOfRangeException(    "Invalid index: " + index);  
     }  
     GrowIfArrIsFull();  
     Array.Copy(this.arr, index,   this.arr, index + 1, this.count - index);          
    this.arr[index] = item;  this.count++; }  

    private void GrowIfArrIsFull() 
    {  
    if (this.count + 1 > this.arr.Length)  
    {   
      T[] extendedArr = new T[this.arr.Length * 2];  
      Array.Copy(this.arr, extendedArr, this.count);  
      this.arr = extendedArr;  
    } 
  }
 }
}

Comments