4
\$\begingroup\$

This code is about manipulating each value in a 2D array. My method below is called based on how I want the values in the array to be manipulated (process).

For the first method in the switch statement - as an example, I am calling AllCaps() method to manipulate the value.

What I am trying to avoid is repeating statements when I can put it in a method instead and just call it when needed. With my code below, though, it seems like I am making the program work too hard by performing a check on each iteration - which could be in the thousands.

Is it effective to call a method for processing each 2D array value inside the nested for loop? Or call the method first and perform the nested for loop inside each method?

private void ProcessSelectedRange(string process)
{
 selectedRange = GetSelectedRange();
 // initialize and populate 2d array with values from selected range
 curValue = new object[,] { };
 curValue = selectedRange.Value;
 // possibly more statements
 // loop through curValue 2d array
 for (int i = 1; i <= curValue.GetLength(0); i++)
 {
 for (int j = 1; j <= curValue.GetLength(1); j++)
 {
 string str = string.Empty;
 // continue if curValue[i, j] is null or empty
 try
 {
 str = curValue[i, j].ToString();
 if (string.IsNullOrEmpty(str)) continue;
 }
 catch { continue; }
 //********************************************************************
 // call method depending on what we want to do with the value
 switch (process)
 {
 case "AllCaps": AllCaps(str); break;
 case "Process2": Process2(str); break;
 case "Process3": Process3(str); break;
 case "Process4": Process4(str); break;
 // possibly more methods
 default: Process5(str); break;
 }
 //********************************************************************
 }
 }
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Aug 24, 2015 at 1:42
\$\endgroup\$
0

2 Answers 2

3
\$\begingroup\$

Exception

Avoid getting them being thrown if possible, as they are costly.

if (curValue[i, j] == null)
 continue;
var str = curValue[i, j].ToString();
if (string.IsNullOrEmpty(str))
 continue;

Loop

The condition will be evaluated every cycle. You do not need to GetLength on each of the loop. The result can be cached :

// could be named rowCount and columnCount; I am not sure which is which
var length0 = curValue.GetLength(0), length1 = curValue.GetLength(1)
// when you have 2 for-loop like that, you don't need to intend all of them
// this is mostly a style choice, but it helps to prevent building a pyramid
for (int i = 1; i <= length0; i++)
for (int j = 1; j <= length1; j++)
{
 // ...
}

The switch part can be moved out of the loop, as the process doesn't change during the loop. This can save us from some string comparisons.

Action<string> processString;
switch (process)
{
 case "AllCaps": processString = AllCaps; break;
 case "Process2": processString = Process2; break;
 case "Process3": processString = Process3; break;
 case "Process4": processString = Process4; break;
 // possibly more methods
 default: processString = Process5;
}
for (...)
for (...)
{
 // ...
 processString(str);
}
answered Aug 24, 2015 at 3:49
\$\endgroup\$
3
  • \$\begingroup\$ Caching the lengths may not be necessary. The compiler should inline and cache them for you as it does with Array.Length, IIRC. \$\endgroup\$ Commented Aug 24, 2015 at 6:48
  • 2
    \$\begingroup\$ Please use bracing and indenting in the for loops. Building a pyramid is prevented by refactoring, not be not indenting \$\endgroup\$ Commented Aug 24, 2015 at 7:46
  • \$\begingroup\$ I like this. Thank you for pointing out the Exception. With Loop, I try not to use a variable if I am only using the value once. I think I remember convincing myself that I may be saving some memory allocation by minimizing the use of variables - for one time use. In this case though I understand your point. Action<>. Now this is interesting. This may also be the answer to one of the programs I am working on. This is enlightening. Thank you. \$\endgroup\$ Commented Aug 24, 2015 at 13:29
3
\$\begingroup\$

Removing the check on each iteration is definitely a good idea. My advice: have a separate method for each process. E.G.

SelectedRange = GetSelectedRange()
AllCapsRange(SelectedRange)
Process2Range(SelectedRange)

then, if you need to select a case, you only need to do it once, and not \$n^2\$ times.

As a general rule, the ONLY things that should go inside an iterative loop are things which could change during the iteration. Anything else should be declared/set beforehand.

Quill
12k5 gold badges41 silver badges93 bronze badges
answered Aug 24, 2015 at 2:21
\$\endgroup\$
1
  • \$\begingroup\$ Thank you for sharing your view Zak, and I like your general rule. I'll keep that in mind. \$\endgroup\$ Commented Aug 24, 2015 at 13:31

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.