Assign a method with default values to Func<> without those parameters? - c#

I would like to be able to do the following:
Func<int,bool> tryMethodFunc = TryMethod;
Where TryMethod has a signature like:
bool TryMethod(int value, int value2 = 0, double value3 = 100.0)
I'm not opposed to breaking the method up into a curried format but that would be more work if there is a way to do this without that.

Optional parameters is a language feature, the compiler is responsible for translating the calls to methods with optional parameters to full call with values.
Look at this simple piece of code below,
public void GeneralMethod()
{
TestMethod(6);
}
public bool TestMethod(int a, int b = 8)
{
return true;
}
When you disassemble these methods, you will see that the C# compiler actually replaced the call to TestMethod with one parameter to a call with both the parameters. The screen shot from ildasm proves that,
Now, Coming to current problem, the line of code in question is trying to bind a Func with a method that has optional parameters. If C# compiler have to handle this, it has to ensure that the Func some knows the default values. While this could have been achieved by compiler, it completely defeats the purpose of Func.
Purpose of Func is to provides a way to store anonymous methods in a generalized and simple way." reference
Another similar question in stackoverflow can be found here
#Chris Sinclair's solution works around this by creating an anonymous method that takes one parameter and calls the TryMethod from the body of this anonymous method.

Related

Is it possible to simply pass a generic method with generic parameters as an argument to another method in C#?

For a test, I want to create a generic "helper" method which will take take two arguments, the first argument is a function (or a reference to the function) and the 2nd argument is a list of objects for that function that are to be called as its parameters.
The following does this perfectly:
CallMyFunctionWithParamsPlease(new Func<int, int>(MyMethod), new object[] {1});
public static int CallMyFunctionWithParamsPlease(Delegate func, params object[] args)
{
func.DynamicInvoke(args);
return 3;
}
The thing is, this doesn't look very nice when calling it and I wish to abstract it into another method to act as syntatic sugar.
Ideally I want it to be called like this:
CallMyFunctionWithParamsPlease(myMethod, new Object[] {1});
From what I can gather, there is no elegant solution to do this in C# since I cannot pass myMethod by itself as a reference anywhere, instead I must pass it by declaring a new Func along with the return type of the method. Since I'm not using this return type anywhere, I'm not sure why it's necessary to input this information. My limited understanding is that because C# is statically typed, the compiler must know everything and things like this just aren't possible.
Is this true or not? How would I create syntatic sugar to simply pass a method to another method which can be called there without needing to invoke "new Func"? I would have thought simply passing the function as a reference pointer would allow me to do this, but I'm having difficultly doing this too. I looked into delegates, using "unsafe" with pointers, and a few other options. None of them seem to make this possible, or if they do, they didn't explain it in a manner that I could understand.
I simply want to pass a method to another method, and invoke it with a variable list of object params with variable length whereby I don't need to specify this whilst invoking it. I'm not sure if I'm trying to force C# to do something it's not meant to do here, and instead I'd be better off using a dynamically typed language to do this. The problem is I really enjoy the intellisense that the static typing of C# offers, along with the performance improvements over a language like Python. I'd just like a way to syntactically abstract away the boilerplate with my own helper methods for things like this.
UPDATE: Thanks to the comments here it seems I can do this with a lambda expression nice and elegantly. The signature can be simply changed to public static long CallMyFunctionWithParamsPlease<T>(Func<T> func)
If deferred execution is what you want simply pass a Func<TReturnType> to your method (or class). The calling method doesn't need to know how many parameters are involved.
e.g. Assuming MyMethod has a signature int MyMethod(int arg):
CallMyFunctionWithParamsPlease(() => MyMethod(1));
public static int CallMyFunctionWithParamsPlease(Func<int> func)
{
return func();
}
If MyMethod takes two parameters, it's the same call:
CallMyFunctionWithParamsPlease(() => MyMethod(1, 2));

What is the value being passed into this lambda expression?

Forgive me if this is a stupid question but I am not sure where to look. I have this code that compiles fine:
static int Main(string[] args)
{
var parserResult = CommandLine.Parser.Default.ParseArguments<Options>(args);
parserResult.WithParsed<Options>(options => OnSuccessfulParse(options));
parserResult.WithNotParsed<Options>(errs =>
{
var helpText = HelpText.AutoBuild(parserResult, h =>
{
return HelpText.DefaultParsingErrorsHandler(parserResult, h);
}, e =>
{
return e;
});
Console.WriteLine(helpText);
ReturnErrorCode = ErrorCode.CommandLineArguments;
});
return (int)ReturnErrorCode;
}
My query has to do with this line of code:
parserResult.WithParsed<Options>(options => OnSuccessfulParse(options));
I understand that with a Lambda Expression the value on the left of the => is the value and value on the right is the expression.
What exactly is options? Why does it compile? It works absolutely fine. But what is it?
I don't know if this helps:
I might be barking up the wrong tree with my understanding of this. I admit I am struggling with the concept. Any explanation appreciated.
I see several questions but I can't explain it in my situation.
Update
OnSuccessfulParse declaration is:
private static void OnSuccessfulParse(Options options)
The WithParsed code is provided here
Lambda expression is the delegate of type Action<Options>. It is a callback from the parser into your code to inform you that the parse has been successful, and pass you Options object obtained as the result of the parse.
As far as options goes, it's just a name that you picked for the parameter to be passed into OnSuccessfulParse method. It is completely unnecessary here - this method group equivalent call will compile and run just the same:
parserResult.WithParsed<Options>(OnSuccessfulParse);
Here is the definition of WithParsed<T> method from github project:
public static ParserResult<T> WithParsed<T>(this ParserResult<T> result, Action<T> action)
{
var parsed = result as Parsed<T>;
if (parsed != null) {
action(parsed.Value);
}
return result;
}
This method is rather straightforward: it takes parse result, tries casting it to a successful parse, and if the cast is valid, calls a delegate that you supply. The WithNotParsed<T> method casts to unsuccessful NotParsed<T> result, and makes a call if the cast is valid.
That's a C# (.Net) way of representing function blocks.
Essentially an Action<Type> is an invocable type that roughly means pass an instance of Type in and execute the block.
E.g. we can write
public void Do(){
this.CallStuff(s => Console.WriteLine(s)); // or you can use a method group and do this.CallStuff(Console.WriteLine);
}
public void CallStuff(Action<string> action){
var #string = "fancy!";
action(#string);
}
In this case the s type is string.
In your example there is a type called Options defined somewhere and it is passed into an action.
Additionally, if you look at decompiled code, anonymous method blocks passed to actions are compiled as static anonymous types inside your class (because c# does not support dynamic code blocks, like, for example, obj-c does).
Another thing to look into are Func<out type> -> these are essentially the same as Action<> except the LAST type in the generic definition is the type they return.
UPD
#elgonzo raises a good point - Action<> and Func<> are actually just delegates; meaning that you can define a real method and pass it along as an Action or Func and then no anonymous static class will be compiled.
However in practice you will see that a lot of code defines those inline, and then the in-line code block needs to reside within a method somewhere, so the compiler puts it into the statis anonymous class.
What exactly is options?
options is i/p parameter to delegate represented by lambda expression
Why does it compile?
Simply because it adheres all syntactical and semantic rules of compiler ;) Like (x)=>x+1 is lambda expression to represent Func<int,int> (there can be another delegate to match same signature as well)
If your method expects Func<int,int> as parameter and argument passed is (x)=>x+1 then compiler infers this as x of type int. Compiled IL code would be equivalent to passing instance of delegate as an argument to method. Like :
call((x)=>x+1) will be compiled to call(new Func<int,int>(myMethod)) where call method definition is :
void Call(Func<int,int> someparam) {}
But what is it?
I think above response should have addressed this query.

Is this the right way to overload a method?

I am working on my own command line arguments parser and after reading dozens of articles regarding method overloading I am still not certain if I am doing it right.
Am I getting any benefit from overloading methods this way? I know I could just write the entire thing in a single method (with default value parameters) by branching, but I'm experimenting overloads at the moment and I would like to know whether to continue on this path or not.
public static class MyParsers
{
private static List<string> args;
static MyParsers()
{
args = Environment.GetCommandLineArgs().ToList();
}
public static List<string> ParseOptions()
{
return ParseOptions(false);
}
public static List<string> ParseOptions(bool toLowercase)
{
// DEBUG: Change command line arguments here.
var arguments = args;
return !toLowercase
? arguments
: arguments.MyExtToLower();
}
public static bool OptionExists(string option)
{
return OptionExists(option, false);
}
public static bool OptionExists(string option, bool toLowercase)
{
var list = ParseOptions(toLowercase);
for (var i = 1; i < list.Count; i++)
{
if (list[i].StartsWith(option)) return true;
}
return false;
}
}
Yes that is the correct way to use overloads.
One thing to note about default parameters.
If you have two assemblies, A and B, A calls the function in B.
If you change the default in B:
using default values for parameters you need to recompile both assembly A and B for this change to take effect
using overloads you only need to recompile B.
This is because for default parameters, at compile time the compiler inserts the default values.
Yes, that's fine.
As you already know, you could also use optional parameters with default values, if your overloads only call another method with a default value (this would reduce the number of line of code).
Yep, this is how overloads work.
But a side-node:
Do you need your code to be used from languages which don't support
optional parameters? If so, consider including the overloads.
Do you have any members on your team who violently oppose optional parameters? (Sometimes it's easier to live with a decision
you don't like than to argue the case.)
Are you confident that your defaults won't change between builds of your code, or if they might, will your callers be okay with that?
Source: Should you declare methods using overloads or optional parameters in C# 4.0?
The "problem" with optional parameters is that if the default value is changed in some future version X of your assembly A then any client assemblies C that reference A will need to be recompiled in order to "see" the change -- loading an updated version of A will cause them to call the new methods with the old default values.
If this is not a potential problem then using optional parameters is more convenient. The equivalent version that emulates optional parameters using multiple overloads does not have this issue because in that case the default value is baked into assembly A instead of into C.
I think your style of overloading is fine.
If you thought you might have loads of different parsing arguments (ToUpperCase etc)
rather than have one class with lots of overloaded methods you might consider using object inheritance and have a LowerCaseParser, CamelCaseParser etc...

How does CLR resolve method involving a dynamic type?

Given,
Method overloading = compile time resolution.
Method overriding = run-time resolution.
How does CLR resolve the following method call (involving a dynamic type) ?
dynamic intValue = -10;
var result = Math.Abs(intValue);
Thanks for your interest.
The process of connecting names to what they are is called binding. Normal overload resolution is 'early' binding, because the exact meaning of the method name is determined early - at compile time.
When the compiler encounters a virtual method during overload resolution, it emits a virtual call. At runtime, this is routed to the correct method, possibly to an override.
When the compiler encounters a dynamic object, it emits code to perform 'late' binding, i.e. at runtime. Late binding is like overload resolution at runtime. The code looks at the argument, finds out its an integer, looks up the correct overload to call, and calls it.
Well, it actually does a bit more than that. It caches the result of the lookup and puts in a test so that the next time the code is run, it can go right to calling the correct method if the argument type is int.
This is still a simplification. In reality, several more optimizations may be done to gain optimal performance.
See this blog post for a more thorough explanation of exactly what would happen with your example.
Method binding that involves dynamic type parameters is a bit tricky in C#. The first and basic rule the compiler uses is: Types take precedence over dynamic. for example:
void method(dynamic x, string y)
{
//do something
}
void method(int x, string y)
{
// do something
}
a call to the method with arguments int and string method(5,"some string) would be resolved to the second function. However if the parameters of either of the methods were both dynamic the compiler would complain about ambiguous method call.

Ambiguous call error, both functions have different return types

I have two overloaded methods, both called FunctionX. One of them returns a Boolean object, and one a predefined class called Logs.
The error I'm getting is: The call is ambiguous between the following methods or properties: 'FunctionX(string)' and 'FunctionX(string)'.
In one of my other methods, I call FunctionX(string), expecting the Log object, but it's throwing this error. I thought the compiler was supposed to look at the return type and figure this out for itself. How can I fix this?
While languages like Perl and Haskell do support overloading by return type, function overloading by return type is not supported by most statically typed languages. So, it is better if you do not make this trivial problem a part of your code.
Added:
You can find more answers in an earlier Stackoverflow discussion here:
Function overloading by return type?
You cannot have more then one function using the same signature e.g.
string Function1(bool t)
int Function1(bool t)
You need to call each function different names, or having different params e.g.
string Function1(bool t)
int Function1(bool t, int g)
You can't overload a method to have different return types. How would the compiler know what to call here?
string Foo() { /* ... */ }
int Foo() { /* ... */ }
object f = Foo();
Language designers need to take all circumstances into account, not only those that are most trivial.
There is no way for the compiler to distinguish between functions with the same method signature except for the return type. And as far as I know no compiler can that is strongly typed. You must change the signature in some way. On option is to use a generic function and provide the return type.
The return type does not partecipating on overloading in C#.
You can, for example:
Declare separate functions FunctionXToLog and FunctionXToBool
FunctionX(string s, out Log logobject), FunctionX(string s, out bool value)
Just to give you a hint.
You cannot have two function with the same signature only differing in return value!
The signature of a method is its name and the types of its parameters - only. Its return type is not part of its signature.
Hence the problem you are having, since the two methods have identical signatures. The compiler does not use the return type, or the type of the object being assigned to, to determine which method to call.
You will have to specify the classname of the method you want (assuming that the two methods are in different classes). Or you will have to provide another parameter for one of the methods, to give it a different signature. Or, finally, you will have to rename one of the methods to make them unambiguous.

Categories