Click here to Skip to main content
15,889,808 members
Please Sign up or sign in to vote.
1.50/5 (2 votes)
See more:
Hello Everyone,
I have a function, the function is supposed to return a value with the same type as the function, but the problem is that the return line is nested in a for loop within the function.

Note: i have tried return null after the for loop, but error appears.
How can i solve this problem?
Thanks in advance,
z3ngew

Moved from non-solution:
C#
public CircleF Capture_Piece(Image<gray,> image)
{
	using (MemStorage storage = new MemStorage())
	{
		for (Contour<point> contours =  image.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
			Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST); contours != null; contours = contours.HNext)
		{
			Contour<point> current_contour = contours.ApproxPoly(contours.Perimeter * 0.01, storage);
			if (current_contour.Area > 250)
			{
				Point[] pts = current_contour.ToArray();
				PointF[] ptsF = Array.ConvertAll(pts, new Converter<point,>(General.PointToPointF));
				CircleF circle = PointCollection.MinEnclosingCircle(ptsF);
				//return circle;
			}
		}
	}
}
Posted
Updated 16-Jan-13 8:56am
v3
Comments
BC @ CV 16-Jan-13 14:44pm    
How about showing us your code?
BC @ CV 16-Jan-13 15:00pm    
WOW! that is one heck of a for statement. Is there a particular reason you're using that syntax?
z3ngew 16-Jan-13 15:09pm    
I'am using a library

You can (in theory) use a return at any point in your code, but there are those who will complain that you should have one exit, and one only. Me, I disagree - error exits are fine by me, as are "obvious" exits - where it would mess up the flow too much to make a "normal" exit worthwhile.
So it is perfectly legal to do this:
C#
private MyClass MyMethod(List<MyClass> list)
    {
    foreach (MyClass mc in list)
        {
        if (mc.UserName == "Exit")
            {
            return mc;
            }
        }
    return null;
    }
Or this:
C#
private MyClass MyMethod(List<MyClass> list)
    {
    for (int i = 0; i < list.Count; i++ )
        {
        if (list[i].UserName == "Exit")
            {
            return list[i];
            }
        }
    return null;
    }
But I would go with the former, as I have no need to know the index, or the number of items.
 
Share this answer
 
Comments
z3ngew 16-Jan-13 14:56pm    
Good Idea, Thanks
z3ngew
Sergey Alexandrovich Kryukov 16-Jan-13 18:11pm    
Agree, my 5.
I also answered to OP's question about unusable null; there are 3 approaches, please see.

Now, as to "one and only one exit". I think this requirement is poorly idiotic. I was surprised when I heard about it from someone on CodeProject.

I mean, "one and only one exit" can be useful sometimes; the idiotic is the requirement to enforce it as a discipline. It is not a consequence of any theoretical computer science theorem or something like that, this is merely a "practical" (quotation marks intended) rule stemmed from some old advice which could be based on some lousy compiler for some lousy language. This is a pure superstitious approach "if I don't understand it, I will do as they taught me at school". Instead of using one's brain. And very basic use of one's brain should reveal that in a language like C# diagnostics is so good and clear, that this can hardly be an issue for any code written in reasonably clear style.

And learning cookbook recipes instead of thinking... (sight...)

—SA
OriginalGriff 17-Jan-13 3:07am    
Agreed - one exit can confuse the code far too much: for example if you have nested loops.
Sergey Alexandrovich Kryukov 17-Jan-13 3:22am    
That is true, too. Not confuse, but perhaps introduce unwanted complications. "Accidental complexity", the name of it.
—SA
Maybe you could simplify your code and add returns like this:

C#
public CircleF Capture_Piece(Image<gray> image)
{
    using (MemStorage storage = new MemStorage())
    {
       Contour<point> contours =  image.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST);

       while (contours != null)
       {
           Contour<point> current_contour = contours.ApproxPoly(contours.Perimeter * 0.01, storage);
           if (current_contour.Area > 250)
           {
                Point[] pts = current_contour.ToArray();
                PointF[] ptsF = Array.ConvertAll(pts, new Converter<point,>(General.PointToPointF));
                CircleF circle = PointCollection.MinEnclosingCircle(ptsF);
                        return circle;
            }
            contours = contours.HNext;
        }
        return null;
    }
}
 
Share this answer
 
Comments
z3ngew 16-Jan-13 15:10pm    
return null is not working == error
BC @ CV 16-Jan-13 15:11pm    
Is CircleF a value type?
z3ngew 16-Jan-13 15:18pm    
Yes, CircleF is a data type
anyway i managed to get a solution, but not very perferct
it is simply by return an null value of that type,

Thanks for support,
z3ngew
BC @ CV 16-Jan-13 15:22pm    
If it is a value type you will not be able to return null, but you can return the default value for that type.
z3ngew 16-Jan-13 15:26pm    
Yes, Thanks for the tip,
z3ngew
z3ngew wrote:
return null is not working == error
There are three approaches to it.

  1. Turn CircleF from struct to class.

    In almost all cases, this is perfectly safe, safer then the other way around. It will work immediately. In most cases, this is the best solution.
  2. Use a different pattern: special "not an object" value to express the concept of null. It could be any "special" value, such as a circle with zero or negative radius. In the structure, create a Boolean predicate method checking if this is a "null" object, to have the implementation detail of this criterion private in the structure. You are also advised to have a special static factory method to produce an instance of such "null" object, again, in the code of the same structure, to hide implementation detail.

    When you have it, you should create such object instead of "null" for your return, pretty much the way you do it now.
  3. If CircleF is a value type, you can always turn it into a nullable object using the type CircleF?. This approach is mostly used for primitive and enumeration types. It will work for struct as well, so you would be able to use null as with classes. Please see:
    http://msdn.microsoft.com/en-us/library/1t3y8s4s%28v=vs.110%29.aspx[^].

    However, it does no make much sense, as you can better use the first approach instead. Nevertheless, it's better to know about it.


—SA
 
Share this answer
 
v6
Comments
z3ngew 16-Jan-13 18:23pm    
Your second approach works well for me, i wasn't able to Turn CircleF to struct since it is in a part of a library that i am using.

Thank you for your time,
z3ngew
Sergey Alexandrovich Kryukov 16-Jan-13 18:26pm    
...That's why I found it useful to list all the possibilities.

The 3rd approach would also work for you, as CircleF? is a type derived from CircleF. As the function in question and the calls of it are all yours, it would also work without much extra effort...

You are very welcome.
Good luck, call again.
—SA
Espen Harlinn 16-Jan-13 18:31pm    
5'ed!
Sergey Alexandrovich Kryukov 16-Jan-13 18:42pm    
Thank you, Espen.
—SA
Change your method to:
public bool Capture_Piece(Image<gray,> image, out CircleF result)
{
  
 using (MemStorage storage = new MemStorage())
 {
  for (Contour<point> contours =  
      image.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
      Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST); 
     contours != null; 
     contours = contours.HNext)
   {
     Contour<point> current_contour = 
        contours.ApproxPoly(contours.Perimeter * 0.01, storage);
     if (current_contour.Area > 250)
     {
       Point[] pts = current_contour.ToArray();
       PointF[] ptsF = 
            Array.ConvertAll(pts, 
               new Converter<point,>(General.PointToPointF));
       result = PointCollection.MinEnclosingCircle(ptsF);
       return true;
     }
    }
  }
 result = new CircleF(new PointF(0, 0), 0);
 return false;
}


You can then test for a true/false return from your function, and using an out parameter to return the CircleF is slightly more efficient than boxing and unboxing the struct.

Best regards
Espen Harlinn
 
Share this answer
 
v2
Comments
z3ngew 16-Jan-13 18:44pm    
Your method is just perfect, but you cannot return false just like that, you have to give a value(null value) to result

result = new CircleF(new PointF(0, 0), 0);
return false;

Many Thanks,
z3ngew
Espen Harlinn 16-Jan-13 18:47pm    
True, I was focusing on the mix of an out parameter with a bool return value ... so that little error crept in ...
z3ngew 16-Jan-13 18:48pm    
Works Great!
Sergey Alexandrovich Kryukov 17-Jan-13 16:45pm    
Sure, a 5.
—SA
Espen Harlinn 17-Jan-13 16:46pm    
Thank you, Sergey :-D

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900