Reputation: 61
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
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
Reputation: 140
I think you can achieve what you are describing by passing a Predicate to your function as a parameter.
Upvotes: 1