Reputation: 1303
Say I have a method that calls another method that accepts a string and returns a string, over and over until a condition is met:
public string RetryUntil(
Func<string, string> method,
string input,
Func<string, bool> condition,
TimeSpan timeSpan)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
string response = string.Empty;
bool conditionResult = false;
while (stopwatch.Elapsed < timeSpan && conditionResult != true)
{
result = method(input);
conditionResult = condition(result);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
return response;
}
It really feels like I should be able to specify the 'method' and 'input' parameters as one parameter. So, I want to refactor it so I am able to call it like this, for example:
RetryUntil(
ConvertString("hello World"),
(str) => { return str == "whatever"; },
TimeSpan.FromSeconds(10));
But obviously, this would pass the result of calling the ConvertString method, (rather than just a delegate to that method) into the Retry method. Is there a way to pass both delegates and specific parameters for those delegates as one? Am I thinking about the entire problem backwards? It just feels a bit inelegant the way I'm doing it now.
Upvotes: 3
Views: 83
Reputation: 10708
What you're looking for is often called "currying" and is not directly supported in C#, or at least not as well as it is in F#. This is a feature where you can specify some arguments of a function, and get a delegate which takes the remaining arguments (if any) and returns the appropriate value.
The easiest way to reference this is like so:
public string RetryUntil(
Func<string> method,
Func<string, bool> condition,
TimeSpan timeSpan)
And then call via
RetryUntil(
() => ConvertString("Hello World!"),
// ...
the =>
creates a lambda, which will return the result of the given function. Since you're now declaring a method call, you can pass in whatever parameters you wish, or make the lambda itself take some parameters, thus currying arguments.
Upvotes: 3