user3447171
user3447171

Reputation: 61

Breaking out of a recursive loop to check a condition, is this possible?

I have a situation where I need to use the same recursive loop but check different conditions before looping back around.

Here is my recursive method;

private static CategoryFeatureType GetParentCategoryType(
        DMS.ProductLocation productLocation, DMS.ProductLocation[] productLocations, 
        Dictionary<string, CategoryFeatureType> categoryFeatureTypes, 
        int level)
{
    CategoryFeatureType categoryFeatureType = null;

    categoryFeatureTypes
            .TryGetValue(productLocation.ExternalChannelCode, 
                         out categoryFeatureType);

    // Here is where i want to return the object to perform a conditional check
    // and come back into the method if needed.
    return categoryFeatureType;

    if (conditionTypeCollection == null && 
        productLocation.ProductLocationIdForParent.HasValue)
    {
        DMS.ProductLocation parentLocation = productLocations
            .FirstOrDefault(p => 
                p.Id == productLocation.ProductLocationIdForParent);

        if (parentLocation != null)
        {
            conditionTypeCollection = GetParentCategoryTypeCollection(
                                          parentLocation, 
                                          productLocations, 
                                          categoryFeatureTypes, 
                                          level + 1);
        }
    }
}

Normally, I'd have the conditional check inside of the method but as it needs to be used in different situations that will use different conditional checks.

I could use create a method for each conditional check but I'd rather not do this.

If this possible in C# or am i going about it an incorrect way?

Upvotes: 4

Views: 143

Answers (2)

Chris Sinclair
Chris Sinclair

Reputation: 23208

You could have callers pass in a delegate that returns a bool (say, Predicate<CategoryFeatureType>). Your GetParentCategoryType method will simply invoke the delegate and use its returned true or false value to dictate if you break. When recursing, you can pass that same delegate through:

private static CategoryFeatureType GetParentCategoryType(
    DMS.ProductLocation productLocation, 
    DMS.ProductLocation[] productLocations, 
    Dictionary<string, CategoryFeatureType> categoryFeatureTypes, 
    int level, 
    Predicate<CategoryFeatureType> shouldBreak)
{
   CategoryFeatureType categoryFeatureType = null;

   categoryFeatureTypes.TryGetValue(productLocation.ExternalChannelCode, out categoryFeatureType);

   if (shouldBreak(categoryFeatureType))   
        return categoryFeatureType;

   if (conditionTypeCollection == null && productLocation.ProductLocationIdForParent.HasValue)
   {
       DMS.ProductLocation parentLocation = productLocations.FirstOrDefault(p => p.Id == productLocation.ProductLocationIdForParent);
       if (parentLocation != null)
       {
           conditionTypeCollection = GetParentCategoryTypeCollection(
            parentLocation, 
            productLocations, 
            categoryFeatureTypes, 
            level + 1, 
            shouldBreak);
       }
   }
}

Then you can wrap this method with ones that pass in a predefined delegate:

private static CategoryFeatureType GetParentCategoryTypeWhereTypeIsAwesome(
    DMS.ProductLocation productLocation, 
    DMS.ProductLocation[] productLocations, 
    Dictionary<string, CategoryFeatureType> categoryFeatureTypes, 
    int level)
{
    Predicate<CategoryFeatureType> returnCheck = categoryFeatureType =>
    {
        return categoryFeatureType.Coolness == "Awesome";
    };

    return GetParentCategoryType(
        productLocation, 
        productLocations, 
        categoryFeatureTypes, 
        level, 
        returnCheck);
}

If you wanted to execute it without a conditional check, you could check for a null delegate or your can pass in a delegate that always returns false:

if (shouldBreak != null && shouldBreak(categoryFeatureType))   
    return categoryFeatureType;

Or with an empty wrapper:

private static CategoryFeatureType GetParentCategoryTypeNeverExit(
    DMS.ProductLocation productLocation, 
    DMS.ProductLocation[] productLocations, 
    Dictionary<string, CategoryFeatureType> categoryFeatureTypes, 
    int level)
{
    Predicate<CategoryFeatureType> returnCheck = categoryFeatureType =>
    {
        return false;
    };

    return GetParentCategoryType(
        productLocation, 
        productLocations, 
        categoryFeatureTypes, 
        level, 
        returnCheck);
}

Upvotes: 2

JoyalToTheWorld
JoyalToTheWorld

Reputation: 140

I think you can achieve what you are describing by passing a Predicate to your function as a parameter.

Upvotes: 1

Related Questions