1

I have a condition let's assume for example Animal = {Dog,Cat,Elephant}

Now I want to make a for loop with if conditions in it (not a simple for loop), inside this for loop I do some code based on the animal type for example:

for(int i=0;i<100;i++)
{
  if(some conditions on i)
  {
   for(int j =0;j<100;j++)
   {
     if(some condition on j)
     {
       switch(animaltype)
       {  
         case Dog: //call function 1
         case Cat: //call function 2
         case Elephant: //call function 3
       }
     }
   }
  }
}

So for performance optimization in case of large loops I made the switch-case outside the for loop so the code became something like this:

switch (animaltype)
{
case Dog :
    for(int i=0;i<100;i++)
    {
      if(some conditions on i)
      {
       for(int j =0;j<100;j++)
       {
         if(some condition on j)
         {
           //call function 1
         }
       }
      }  
    }
//-------------
case Cat :
    for(int i=0;i<100;i++)
    {
      if(some conditions on i)
      {
       for(int j =0;j<100;j++)
       {
         if(some condition on j)
         {
           //call function 2
         }
       }
      }  
    }
//----------------------
case Elephant :
    for(int i=0;i<100;i++)
    {
      if(some conditions on i)
      {
       for(int j =0;j<100;j++)
       {
         if(some condition on j)
         {
           //call function 3
         }
       }
      }  
    }
}

The problem here is that I repeated the code 3 times (or as the number of cases) and this violates the once and only once principle of the Software Design.

I tried to pass a delegate but the 3 functions that I supposed to call have different arguments, can anyone tell me a neat solution to this case?

EDIT I mean by "different arguments" that they do not take the same number of arguments. For example:

function1(string s,int age)
function2(float height,bool CanMove)
function3(int legs,string name,string place)
8
  • 6
    That's the reason why methods exist. Also, don't worry about the performance of a switch. Commented Jun 5, 2014 at 13:08
  • 1
    It would help if you'd give a more complete example. The key will lie in the differences in terms of what you need to do with the animal... (I strongly suspect a delegate is the right solution here, but we can't give a more complete example of the solution without a complete example of the problem...) Commented Jun 5, 2014 at 13:09
  • 3
    Another thing is that you should never prematurely optimize your code. I don't believe you've actually made any performance improvements by rearranging the execution like that. If anything, you've only worsened the readability. Commented Jun 5, 2014 at 13:12
  • 1
    a switch statement is not going to be the performance problem here, it turns into a simple jmp in asm. Commented Jun 5, 2014 at 13:14
  • 1
    Also consider whether the animal should be a class rather than an enum (or string or whatever it is here), with the function as a method on that class. Without knowing what exactly the method is, it's hard to say whether that's the case here Commented Jun 5, 2014 at 13:21

3 Answers 3

2

Try something like this:

void ExecuteLoop(Func callback)
{
    for(int i=0;i<100;i++)
    {
        if(some conditions on i)
        {
            for(int j =0;j<100;j++)
            {
                if(some condition on j)
                {
                    callback();
                }
            }
        }  
    }
}

switch (animaltype)
{
case Dog:
    ExecuteLoop(dogCallback);
    break;
case Cat:
    ExecuteLoop(catCallback);
    break;
case Elephant:
    ExecuteLoop(elephantCallback);
    break;
}

This will allow you to consolidate the loop into a method, while varying what is actually executed. It is unclear when you say:

...but the 3 functions that I supposed to call have different arguments...

what you mean. I assume one of two things:

  • The three methods you intend to call have different values passed as their arguments.

or

  • The three methods you intend to call have a different number of arguments passed to them.

Either way, you can solve this by building on the previous solution. Something like this:

switch (animaltype)
{
case Dog:
    ExecuteLoop(() => { dogCallback(1, 2, 3); });
    break;
case Cat:
    ExecuteLoop(() = > { catCallback( "argument 1", "arg 2" ); });
    break;
case Elephant:
    ExecuteLoop(() => { elephantCallback(i, j, k); });
    break;
}

This uses lambdas that accept no parameters (thus matching the requirement of the ExecuteLoop method) but call a method that accepts any number of variable type arguments.

Sign up to request clarification or add additional context in comments.

1 Comment

Given the amount of information we have from the question, this is probably the best solution.
1

I tried to pass a delegate but the 3 functions that I supposed to call have different arguments, can anyone tell me a neat solution to this case?

Create 3 functions which take no parameters which call your existing functions. For example...

Func HandleDog = ()=>{function1(param1, param2);};
Func HandleCat = ()=>{function2(param1);};

Comments

1

To expand on the answers provided by Robert and William, I personally find this cleaner:

        Action animalMethod;

        switch (animalType)
        {
            case Dog:
                animalMethod = new Action(() => CallMethod1(animal as Dog));
                break;
            case Cat:
                animalMethod = new Action(() => CallMethod1(animal as Dog));
                break;
            case Elephant:
                animalMethod = new Action(() => CallMethod1(animal as Dog));
                break;
            default:
                throw new Exception("Unknown Animal");
        }

        for (var i = 0; i < 100; i++)
        {
            if (some conditions on i)
            {
                for (var j = 0; j < 100; j++)
                {
                    if (some condition on j)
                    {
                        animalMethod();
                    }
                }
            }
        }

2 Comments

For what it's worth, our solutions are exactly the same number of lines of code: 28. Just a fun fact!
The difference though was I kept the for loop in the same method that assigns the call back delegate. Also, I handle the default case in the switch statement and throw a very nicely formatted exception :). But yes, it is mostly stylistic. The performance overhead of an extra method call would be negligible.

Your Answer

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.