Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to "push" into C# array

Tags:

arrays

c#

push

Good day all

So I know that this is a fairly widely discussed issue, but I can't seem to find a definitive answer. I know that you can do what I am asking for using a List, but that won't solve my issue.

I teach a class in beginner C#. I have a PHP and Java Script background, and thus tend to think in terms of these languages.

I have been looking for the best way to show my students how to add elements to an array on the fly.We can't use Lists, as these are not part of the syllabus that I currently teach (although they do come in later in the semester).

I am thus looking for the simplest way to perform a Java array.push(newValue) type scenario that will be understandable to novice coders without teaching them bad practice.

Here is how I have been approaching the problem so far:

for (int i = 0; i < myArray.Length; i++)
{
   if(myArray[i] == null)
   {
       myArray[i] = newValue;
       break;
   }
}

I just need to know if this is an acceptable approach, if I am teaching them any bad practices, or if there is a better / simpler way of achieving my goal.

EDIT The crux of the matter is that the element needs to be added into the first empty slot in an array, lie a Java push function would do.

Any advice would be greatly appreciated.

like image 371
phunder Avatar asked Jul 25 '18 05:07

phunder


2 Answers

array.push is like List<T>.Add. .NET arrays are fixed-size so you can't actually add a new element. All you can do is create a new array that is one element larger than the original and then set that last element, e.g.

Array.Resize(ref myArray, myArray.Length + 1);
myArray[myArray.GetUpperBound(0)] = newValue;

EDIT:

I'm not sure that this answer actually applies given this edit to the question:

The crux of the matter is that the element needs to be added into the first empty slot in an array, lie a Java push function would do.

The code I provided effectively appends an element. If the aim is to set the first empty element then you could do this:

int index = Array.IndexOf(myArray, null);

if (index != -1)
{
    myArray[index] = newValue;
}

EDIT:

Here's an extension method that encapsulates that logic and returns the index at which the value was placed, or -1 if there was no empty element. Note that this method will work for value types too, treating an element with the default value for that type as empty.

public static class ArrayExtensions
{
    public static int Push<T>(this T[] source, T value)
    {
        var index = Array.IndexOf(source, default(T));

        if (index != -1)
        {
            source[index] = value;
        }

        return index;
    }
}
like image 151
jmcilhinney Avatar answered Sep 20 '22 20:09

jmcilhinney


Your question is a little off the mark. In particular, you say "that the element needs to be added into the first empty slot in an array, lie (sic) a Java push function would do."

  1. Java's Array does not have a push operation - JavaScript does. Java and JavaScript are two very different languages
  2. JavaScript's push function does not behave as you describe. When you "push" a value into a JavaScript array, the array is extended by one element, and that new element is assigned the pushed value, see: Mozilla's Array.prototype.push function docs

The verb "Push" is not something that is used with an Array in any language that I know of except JavaScript. I suspect that it's only in JavaScript because it could be there (since JavaScript is a completely dynamic language). I'm pretty sure it wasn't designed in intentionally.

A JavaScript-style Push operation in C# could be written in this somewhat inefficient manner:

int [] myArray = new int [] {1, 2, 3, 4};
var tempList = myArray.ToList();
tempList.Add(5);
myArray = tempList.ToArray();   //equiv: myArray.Push(5);

"Push" is used in some types of containers, particularly Stacks, Queues and Deques (which get two pushes - one from the front, one from the back). I urge you not to include Push as a verb in your explanation of arrays. It adds nothing to a CS student's vocabulary.

In C#, as in most traditional procedural languages, an array is a collection of elements of a single type, contained in a fixed length contiguous block of memory. When you allocate an array, the space for every array element is allocated (and, in C# those elements are initialized to the default value of the type, null for reference types).

In C#, arrays of reference types are filled with object references; arrays of value types are filled with instances of that value type. As a result, an array of 4 strings uses the same memory as an array of 4 instance of your application class (since they are both reference types). But, an array of 4 DateTime instances is significantly longer that of an array of 4 short integers.

In C#, an instance of an array is an instance of System.Array, a reference type. Arrays have a few properties and methods (like the Length property). Otherwise, there isn't much you can do with an array: you can read (or write) from (or to) individual elements using an array index. Arrays of type T also implement IEnumerable<T>, so you can iterate through the elements of an array.

Arrays are mutable (the values in an array can be written to), but they have a fixed length - they can't be extended or shortened. They are ordered, and they can't be re-arranged (except by swizzling the values manually).

C# arrays are covariant. If you were to ask the C# language designers, this would be the feature they regret the most. It's one of the few ways you can break C# type safety. Consider this code (assuming that Cat and Dog classes inherit from Animal):

Cat[] myCats = new Cat[]{myCat, yourCat, theirCat};
Animal[] animals = (Animal[]) myCats;     //legal but dangerous
animals[1] = new Dog();                   //heading off the cliff
myCats[1].Speak();                        //Woof!

That "feature" is the result of the lack of generic types and explicit covariance/contravariance in the initial version of the .NET Framework and the urge to copy a Java "feature".

Arrays do show up in many core .NET APIs (for example, System.Reflection). They are there, again, because the initial release did not support generic collections.

In general, an experienced C# programmer will not use many arrays in his applications, preferring to use more capable collections such as List<T>, Dictionary<TKey, TValue>, HashSet<T> and friends. In particular, that programmer will tend to pass collections around using IEnumerable<T> an interface that all collections implement. The big advantage of using IEnumerable<T> as parameters and return types (where possible and logical) is that collections accessed via IEnumerable<T> references are immutable. It's kinda-sorta like using const correctly in C++.

One thing you might consider adding in to your lectures on arrays - after everyone has mastered the basics - is the new Span<T> type. Spans may make C# arrays useful.

Finally, LINQ (Language Integrated Query) introduced a lot of functionality to collections (by adding Extension Methods to IEnumerable<T>). Make sure your student do not have a using System.Linq; statement up at the top of their code - mixing LINQ in to a beginning student's class on arrays would bewilder him or her.

BTW: what kind of class is it you teach? At what level?

like image 21
Flydog57 Avatar answered Sep 21 '22 20:09

Flydog57