5

I just have a question. I noticed that unlike C++, C# is a bit complicated when it comes to array. One of the features or techniques I've been looking for in the array is that: I want to add elements or remove elements from it in a more efficient and simpler way.

Say for example, I have an array called 'food'.

string[] food = {'Bacon', 'Cheese', 'Patty', 'Crabs'}

Then I decided to add more food. Problem with C# as I can see it is this isn't possible to do unless you do use an ArrayList. How about for an array itself? I want to use the array as some sort of inventory where I add things.

Thanks a lot!

Matt
  • 63
  • 1
  • 7

4 Answers4

5

You can't do that with arrays in C# without allocating a new array. Because arrays are fixed in size.

If you want to be able to add/remove elements from a container, you could use List<T>. Alternativly you could use an ArrayList but that is not recommended, since in most cases List<T> has a performance advantage.

Internally both use an array as the default container for your data. They also take care of resizing the container according to how much data you put in the collection or take out.

In your example, you would use a list like

 List<string> food = new List<string> { "Bacon", "Cheese", "Patty", "Crabs" };

 food.Add("Milk"); //Will add Milk to the list
 food.Remove("Bacon"); //Will remove "Bacon"

List on MSDN: Docs

Tarek
  • 1,219
  • 13
  • 18
  • I didnt downvote, and I dont think your answer is deserving of a downvote but maybe add some examples of using `List`, really "beef up" your answer – maccettura May 18 '18 at 15:14
  • 1
    It does not answer the question, nor do you provide an example. But I have revered the downvote, because it's Friday :-) – Trey May 18 '18 at 15:15
  • Thanks for the feedback, I revised the answer. – Tarek May 18 '18 at 15:20
  • 2
    I would remove `ArrayList` from your answer because its not really a great collection type. Just stick to `List`. Also it might be worth mentioning how `List` uses arrays internally, but it takes care of all that work for you without you having to manage it yourself – maccettura May 18 '18 at 15:24
  • @maccettura thanks for the feedback, I do think that it should be mentioned since it's an actual working solution. But maybe just discourage its use. – Tarek May 18 '18 at 15:33
1

Ideally, if you are going to have a variable size array of strings, a List would be better. All you would have to do is then call list.Add(""), list.Remove(""), and other equivalent methods.

But if you would like to keep using string arrays, you could create either a function or class that takes an array, creates a new array of either a larger or smaller size, repopulate that array with the values you had from the original array, and return the new array.

public string[] AddFood(string[] input, string var)
{
    string[] result = new string[input.Length + 1];
    for (int i = 0; i < input.Length; i++)
    {
        result[i] = input[i];
    }
    result[result.Length - 1] = var;
    return result;
}

public string[] RemoveFood(string[] input, int index)
{
    string[] result = new string[input.Length - 1];
    for (int i = 0; i < input.Length; i++)
    {
        if (i < index) {
            result[i] = input[i];
        }
        else
        {
            result[i] = input[i + 1];
        }
    }
    return result;
}

Again, I would highly recommend doing the List method instead. The only down side to these lists is that it appends them to the end, rather then figuring out where you want to place said items.

List<string> myFoods = new List<String>(food);
myFoods.Add("Apple");
myFoods.Remove("Bacon");
myFoods.AddRange(new string[] { "Peach", "Pineapple" });
myFoods.RemoveAt(2);
Console.WriteLine(myFoods[0]);

There is also ArrayList if you want a list more like an array, but it is older code and unfavoured.

ArrayList myFoods = new ArrayList(food);
myFoods.Add("Apple");
myFoods.Remove("Bacon");
myFoods.AddRange(new string[] { "Peach", "Pineapple" });
myFoods.RemoveAt(2);
Console.WriteLine(myFoods[0]);

I hope this helps.

0

To actually answer the question, you just need to resize the array. Array.Resize(ref array, ); is the new length of the array

Trey
  • 413
  • 4
  • 12
  • 1
    This allocates a new array. – Tarek May 18 '18 at 15:12
  • yes.. it's an array you have to create a new one... I guess he could use an List and then push it to an array. – Trey May 18 '18 at 15:14
  • 1
    `List<>` internally also just uses an array, and whenever it runs out of space it has to rebuild the array too (i.e. allocate new array and copy elements from previous array)... So by using a `List<>` you cannot get rid of the allocation, you just don't have to do it yourself. – bassfader May 18 '18 at 15:18
  • Obviously yes, so does StringBuilder or anything of "expandable/shrinking" size. – Tarek May 18 '18 at 15:21
0

To really add elements to an existing array without resizing you can't. Or, can you? Yes, but with some trickery, which at some point you might say is not worth it.

Consider allocating an array of the size you anticipate it could be. You obviously have to estimate well to avoid tons of unused space. Empty slots in the array would be marked by a sentinel value; for a string the obvious candidate is null. You'd know the "true" size of the array by keeping track of the first index of the sentinel. This suggests that an ArrayWrapper class would encapsulate the array and "true size".

That wrapper could add Add() and AddRange() that replace the sentinel values with real ones without allocating.

All that said, the drawback at some point will be that you have to allocate a new array. Doing this manually using the wrapper is pointless unless you have very specific requirements that allow you to reduce allocations.

So, for the most common cases, stick to a List<>, which does that for you. With the list you can construct it by calling the constructor that takes an initial capacity parameter. Adds will use the underlying array without reallocation until it hits the limit.

In a way that List<> is your wrapper that uses an allocation model the original authors decided would minimize allocations in most cases. That is likely to perform better than anything you write unless you can really leverage your domain.

Kit
  • 20,354
  • 4
  • 60
  • 103