I have a follow static function:
public static string codeList<T>(List<T> thelist, Func<T, string> coder);
using this function with my own objects is not problem for example:
string code = codeList<MyClass>(myclassList, MyClass.code);
Where MyClass.code is a static function (defined in MyClass) that gets MyClass and returns string.
The problem is when I try to use this function with List<int> or List<double> what I do now is predefining statics like Func<int,string> intCoder = (x) => x.ToString(); and Func<double,string> (x) => x.ToString(); and use them.
Is there another way of doing that? something like:
string code = codeList<int>(intList, Int32.ToString);
You can do this with
string code = codeList<int>(intList, Convert.ToString);
It just so happens that Convert.ToString has an overload with the appropriate signature.
The problem with int.ToString is that none of its overloads have the appropriate signature (they don't take an int parameter as it is implied). In that case there would be nothing you could do apart from defining an adapter function.
You don't have to declare a variable for the func. You can just put the lambda expression as the parameter value
string code = codeList(intList, i => i.ToString());
Related
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.
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.
I've looked at a ton of references and have seen that C# supports nested functions through lambda, but I'm completely new to C# (and .NET for that matter). I want to write a flood-fill implementation, with the parameters of a parent function accessible to the nested child.
Here's what it should look like, ideally:
private void StartFloodFill(color,otherstuff,pixel)
{
function Recursion(pixel,color)
{
do(otherstuff);
//etc...
Recursion(pixel,color);
}
}
The Recursion(pixel,color); call is where my confusion lies. I can't access a reference to the function from inside the function.
I know there should be a workaround for this, but I don't know what that is. How can I implement a recursive function like that demonstrated above in C#?
As suggested, you can use a recursive delegate. Normally, you'd declare a delegate like this:
Func<int,int, int> = (a, b) => a+b;
Where Func<int, int, int> is the type of a delegate that takes 2 ints, and returns another int.
But since you want to make it call itself, you have to declare the variable before assigning the delegate.
Func<Pixel, Color, SomeType> func = null;
func = (pixel, color) => {
//do stuff...
if(endCondition)
return someTypeValue;
else
return func(pixel, color);
};
Let's say I have a delegate declaration taking one int as argument:
public delegate void MyDelegate(int i);
private MyDelegate _myDelegate = null;
and I have some function that takes a string and an int as arguments
private MyFunc(string s, int i){
...
}
Now I'd like to create a MyDelegate from MyFunc by specifying the string argument already in advance but leaving the int argument open. something like:
_myDelegate = new MyDelegate(MyFunc("Hello", ?));
whereas the ? would mark the still open argument that would need to be passed when invoking _myDelegate. I know this is is possible in other languages (for example, the ? syntax is comming from Eiffel agents).
how to do this in C#?
You can use a lambda. Since the type can be inferred, you don't need to explicitly say new MyDelegate(...).
_myDelegate = i => MyFunc("Hello", i);
You can use a lambda expression to achieve this kind of partial-function application:
_myDelegate = new MyDelegate(i => MyFunc("Hello", i));
Since _myDelegate is of type MyDelegate, you can also assign it the lambda directly:
_myDelegate = i => MyFunc("Hello", i);
I have a generic function CallLater that should accept an arbitrary other function and possibly call it later with some parameters. All kind of functions should be supported - static, instance, private, public. Parameters are analyzed and constructed dynamically in CallLater with the help of reflection. However, some of them may need to be bound to fixed values before passing the function to the CallLater.
For example:
void CallLater(Delegate d) {
// Expects a function that returns string and has one argument of arbitrary type.
if (d.Method.GetParameters().Length == 1 &&
d.Method.ReturnType == typeof(string)) {
object param1 = Activator.CreateInstance(d.Method.GetParameters()[0].ParameterType);
Console.WriteLine((string)d.DynamicInvoke(param1));
}
}
// Has one extra float parameter.
string MyFunc(int a, float b) { ... }
My idea was to do something like that:
float pi = 3.14f;
CallLater(delegate(int a) { return MyFunc(a, pi); });
But this doesn't work as compiler complains:
Error CS1660: Cannot convert `anonymous method' to non-delegate type `System.Delegate' (CS1660) (test-delegate)
What is the correct approach to achieve my goal?
P.S. Please do not offer the solution to declare a fixed delegate type as CallLater is way more complex and may support variable number of arguments too.
P.P.S. It might be that my solution is Func, but I wasn't able to use it on Mono so far.
You can always redeclare Func yourself:
public delegate TReturn FFunc<TArg,TReturn>(TArg arg);
Which you can use thusly:
float pi = 3.14f;
CallLater((FFunc<int,string>)(delegate(int a) { return MyFunc(a, pi); }));
I'd suggest using anonymous functions in which you call the method you want to execute. These are executed later when the anonymous method is executed.
private static void ExecuteBoolResult(Func<bool> method)
{
bool result = method();
if (!result)
{
throw new InvalidOperationException("method did not return true");
}
}
CheckBoolResult(() => AnotherFunction("with ", 3, " parameters"));
CheckBoolResult(() => AnotherFunction(2, "parameters"));
Is it possible to make a Func delegate an extension method?
For example, just like you could create the function
bool isSet(this string x) {return x.Length > 0;}
I'd like to be able to write something like
Func<string, bool> isSet = (this x => x.Length > 0);
Of course, the above is not syntactically correct. Is there anything that is? If not, is that a limitation in syntax or compilation?
Short answer: no, thats not possible.
Extension methods are syntactic sugar and can only be defined under certain circumstances (static method inside a static class). There is no equivalent of this with lambda functions.
Is it possible to make a Func delegate an extension method?
No. Extension methods have to be declared as normal static methods in top-level (non-nested) non-generic static classes.
It looks like you would be trying to create an extension method only for the scope of the method - there's no concept like that in C#.
To answer the question in comments on why this is wanted you coudl define the isSet func normally and just use that as a method call which will have the same effect as your extension method but with different syntax.
The syntax difference in use is purely that you'll be passing the string in as a parameter rather than calling it as a method on that string.
A working example:
public void Method()
{
Func<string, bool> isSet = (x => x.Length > 0);
List<string> testlist = new List<string>() {"", "fasfas", "","asdalsdkjasdl", "asdasd"};
foreach (string val in testlist)
{
string text = String.Format("Value is {0}, Is Longer than 0 length: {1}", val, isSet(val));
Console.WriteLine(text);
}
}
This method defines isSet as you have above (but without the this syntax). It then defines a list of test values and iterates over them generating some output, part of which is just calling isSet(val). Funcs can be used like this quite happily and should do what you want I'd think.