1

I am sure I am making a foolish mistake here but it beats me. Here is a piece of code:

void Main()
{
    //Key is a parent while the list contains its children
    Dictionary<string,List<string>> d = new Dictionary<string,List<string>>();
    d.Add("1",new List<string>(){"2","3"});//valid.should return false 
    d.Add("2",new List<string>(){"4"});//valid.should return false
    d.Add("3",new List<string>(){"5"});//valid.should return false
    d.Add("4",new List<string>(){"1"});//invalid.should return true 

   IsChildAlreadyAParent("4","2",d);
 }

private bool IsChildAlreadyAParent( string child, string parent, Dictionary<string, List<string>> d )
{           
    if( !d.ContainsKey( child ) || ( d.ContainsKey( child ) && d[child].Count == 0 ))
    {
        return false;
    }

    foreach( string childOfChild in d[child] )
     {
        if( childOfChild == parent )
            return true;

        if( IsChildAlreadyAParent( childOfChild, parent, d ) ) return true;
    }
}

Compiling this gives me this error:

IsChildAlreadyAParent(string, string, System.Collections.Generic.Dictionary<string,System.Collections.Generic.List<string>>)': not all code paths return a value

I have read the code a few times and I cant see how a return condition would be missed. I know I can rectify it by adding a method return statement before the method end but it doesn't help me understand the issue at hand. Where is the gap??

5 Answers 5

6

You might think this executes the loop body exactly once, always returning from the function:

foreach( string childOfChild in d[child] )
{
    if( childOfChild == parent )
        return true;

    return IsChildAlreadyAParent( childOfChild, parent, d );
}

But what if d[child] has no elements at all?

Also, testing only the first child probably isn't the right solution either.

Better:

foreach( string childOfChild in d[child] )
{
    if( childOfChild == parent ) return true;
    if (IsChildAlreadyAParent( childOfChild, parent, d )) return true;
}
return false;
Sign up to request clarification or add additional context in comments.

3 Comments

modified the code to handle that as well...still the same issue and i dont wan't to use a method return at the end as u have done here..
but the point that is raised, "testing only the first child probably isn't the right solution either", was helpful
@wanderer: Sorry, the compiler isn't smart enough to notice that you've already tested for an empty list. So it still is concerned with what happens below the loop.
2

The compiler is complaining because in the case where the d[child] collection is empty the loop body will never run. There is no return on that particular code path and hence you get an error.

Additionally your version of the code will lookup child in the dictionary 3 times on a successful execution. You could optimize this to only do one lookup with TryGetValue.

Here's the code with a couple of fixes

private bool IsChildAlreadyAParent(
  string child, 
  string parent, 
  Dictionary<string, List<string>> d )
{           
    List<string> list;
    if (!d.TryGetValue(child, out list) || list.Count == 0)
    {
        return false;
    }

    if (list[0] == parent)
    {
      return true;
    }

    return IsChildAlreadyAParent(list[0], parent, d );
}

3 Comments

@wanderer my bad, fixed the typo. Should compile now
@wanderer yes, but that's how your original sample functioned. The loop only ever did a single iteration. It either matched parent or it immediately called into IsChildAlreadyAParent with effectively list[0].
@jaredpar....my fault..sorry. was a mistake...i wanted to iterate the complete list checking for the condition.
0

What if d[child] has a length of 0? So your for-loop won't run -> no return value

Comments

0

It might happen that your code never gets into "foreach"...you should have return at the end...if d[child] doesn't have elements at all...

Comments

0

well, what if your list is empty?

Not to mention the foreach loop is pointless. It will always terminate on the first iteration.

Comments

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.