Get the values of each cell in a 2D or jagged array. A foreach loop is needed, which will result in fewer typo bugs and shorter code. We must use an IEnumerable and foreach to loop through all items in a 2D array or collection. Yield and foreach will be important parts.
We know that two-dimensional arrays are enormously powerful and very simple to use, but they can lead to some unwanted complexity. Unfortunately, we require two loops (one for x, one for y) and the code is entirely too complex.
/// <summary>
/// Example class.
/// </summary>
class DataClass
{
/// <summary>
/// The examples will use this two-dimensional array of 225 integers.
/// You would probably have reference objects and something more complex.
/// </summary>
int[,] _numberGrid = new int[15, 15];
/// <summary>
/// Finds the sum of all the numbers in the grid.
/// </summary>
/// <returns>Sum of all numbers.</returns>
public int AddAllNumbers()
{
// This is just a silly example, so don't get too focused on it.
int result = 0;
for (int x = 0; x < 15; x++)
{
for (int y = 0; y < 15; y++)
{
result += _numberGrid[x, y];
}
}
return result;
}
}
Look carefully at the nested loops. In those loops you have many different letters and symbols. Commas, plusses, letters--it is slightly complex. But here's the thing I want to emphasize: This kind of complexity causes bugs to creep into your code.
One advantage with using foreach loops in C# is that foreach eliminates your need to keep track of indexer variables, such as the famous "i" or "x". The code becomes safer and more robust by hiding all the details from the programmers. (We can't be trusted with our own code, I guess.)
Let's look at how we could start implementing an IEnumerable generic collection of the values in our _numberGrid array shown above. Imagine that these new fragments of code are nicely nested in the above class. Right afterwards I will show what the yield return keywords do.
/// <summary>
/// Get enumeration of all items in the 2D array.
/// </summary>
/// <returns>Enumeration of all items in the 2D array.</returns>
public IEnumerable<int> GridValues()
{
for (int x = 0; x < 15; x++)
{
for (int y = 0; y < 15; y++)
{
yield return _numberGrid[x, y];
}
}
}
Now, you need to trust me that there are huge advantages to this IEnumerable method here. For now, let's look at our dumb function AddAllNumbers and rewrite it to use our enumerable collection returned by GridValues.
/// <summary>
/// Find the sum of every item in the 2D array with the enumerator.
/// </summary>
/// <returns>Sum of all numbers in 2D array.</returns>
public int AddAllNumbers()
{
// Just uses the enumerator shown above.
int result = 0;
foreach (int gridValue in GridValues())
{
result += gridValue;
}
return result;
}
C# has many complexities, but some of those complexities are actually undercover simplifications. When I was just learning C#, I felt all these syntax flourishes were complete nonsense. The syntax here augments the vast benefits to using object-oriented programming.
Let's imagine we are writing a somewhat more complex program that uses these 2D arrays in many different places. It doesn't take much thought to determine that we can save complexity with this technique.