C# extension using function Func as parameter - c#

Please don't be confuse with the code, the code is wrong. Focused on the bold question below.
I've been preparing to study functional programming and just so at least be ready for its prerequisites, I've been studying extensions, functions and lambda expressions.
This code below is NOT working I just thought this is how it should be coded:
Program:
class Program
{
static void Main(string[] args)
{
int s = 10;
int t = s.CreatedMethod(2, 3); // <-- the one that calls the extension
Console.WriteLine(t.ToString());
Console.ReadLine();
}
static int RegularMethod(int v1, int v2)
{
return v1 * v2; // <-- I also wanted to multiply int 's' like this s*v1*v2
}
}
Extension:
public static class Extension
{
public static int CreatedMethod(this int number, Func<int, int, int> fn)
{
// I'm expecting that the code here will read the
// RegularMethod() above
// But I don't know how to pass the parameter of the function being passed
return #fn(param1, param2)// <-- don't know how to code here ??
}
}
As you can see, the CreateMethod extended my integer 's'. My plan is to pass the two parameters in CreateMethod() above and multiply those two parameters into 's'
In the example above, the answer should be 60.
Can you help me do it using extension?

This might be what you're looking for but it doesn't make sense to pass a function as a parameter or maybe I'm just missing something. Anyway, it works:
class Program
{
static void Main(string[] args)
{
int s = 10;
// the function we're passing as a parameter will multiply them
// then return the result
int t = s.CreatedMethod((param1, param2) => param1 * param2);
// or you can use this since the method signature matches:
// int t = s.CreatedMethod(RegularMethod);
Console.WriteLine(t.ToString()); // outputs "60"
Console.ReadLine();
}
static int RegularMethod(int v1, int v2)
{
return v1 * v2; // <-- I also wanted to multiply int 's' like this s*v1*v2
}
}
public static class Extension
{
public static int CreatedMethod(this int number, Func<int, int, int> fn)
{
return number * fn.Invoke(2, 3);
}
}
Following up on OP's comment: If you don't want to hardcode the values then you'll need to change the CreateMethod's signature to this:
public static int CreatedMethod(this int number, int val1, int val2, Func<int, int, int> fn)
then call Invoke like this:
fn.invoke(val1, val2)

Extension could look like this:
public static int CreatedMethod(this int number1, int number2, Func<int, int, int> fn) {
fn(number1, number2);
}
And then call would be:
var s = 10;
var t = s.CreatedMethod(2, RegularMethod).
CreatedMethod(3, RegularMethod);
This will first call RegularMethod with 10 and 2 and second time with 20 and 3.
Additional way would be to use extension like
public static int CreatedMethod(this int number1, int number2, int number3, Func<int, int, int> fn) {
fn(fn(number1, number2), number3);
}
And call like
var s = 10;
var t = s.CreatedMethod(2, 3, RegularMethod);

Related

Can not use Func with parameters

I have an example for my problem.
Basically i need to pass a method to another method with parameters included.
public void test() {
var test = Add(Domath(5, 5)); // should be 10
}
public int Domath (int a, int b) {
return a + b;
}
public int Add (Func<int, int, int> math){
return math();
}
It does not work this way and i don‘t know why. This is just a minimalistic example. Is there a way to get this working?
Let's have a look at
public int Add (Func<int, int, int> math){
return math();
}
You can't return return math();: note, that math requires two arguments which are not passed to math(). You can modify Add as
public int Domath (int a, int b){
return a + b;
}
// We are going to add first and second
// with a help of math function
public int Add (int first, int second, Func<int, int, int> math = null) {
// If math is not provided, we use Domath functon
if (math == null)
math = Domath;
// Finally, we call math with required two arguments
return math(first, second);
}
Now you can put
public void test(){
var test = Add(5, 5);
}
Or
public void test(){
var test = Add(5, 5, Domath);
}

My delegate type isn't working "Method name expected"

I tried this:
class Program
{
public delegate int add(int x, int y);
public class ff
{
public static int addNumbers(int x, int y)
{
return x + y;
}
public static int substractNumbers(int x, int y)
{
return x - y;
}
static void Main(string[] args)
{
Delegate delegare = new add(ff.addNumbers);
Console.WriteLine(delegare(3,4));
}
}
I don't see why I'm getting this error"Method name expected".
When I use a delegate with a void function it works.
Can someone help me?
The type of your delegare variable is just Delegate. That could refer to any delegate. In order to invoke a delegate (in the normal way), you should have an expression of the appropriate type.
After fixing the naming conventions and removing the unnecessary nested class - and demonstrating a method group conversion - your code looks like this:
using System;
public delegate int Int32Operation(int x, int y);
class Program
{
public static int AddNumbers(int x, int y)
{
return x + y;
}
public static int SubtractNumbers(int x, int y)
{
return x - y;
}
static void Main(string[] args)
{
Int32Operation op = new Int32Operation(AddNumbers);
Console.WriteLine(op(3, 4)); // Prints 7
op = SubtractNumbers; // Method group conversion
Console.WriteLine(op(3, 4)); // Prints -1
}
}
You should try this out:
add delegare = new add(ff.addNumbers);
The type of your delegate should be add since you defined so.

cannot infer type parameters using Func [duplicate]

This question already has answers here:
Why can't C# infer type from this seemingly simple, obvious case
(5 answers)
Closed 7 years ago.
A colleague wrote this extension method that I wanted to produce an example for:
namespace ExtensionMethods {
public static class MyExtensions {
public static Res MyAggregate<T, Res>(this IEnumerable<T> source, Func<Res, int, T, Res> f) {
var i = 0;
Res result = default(Res);
foreach (T x in source) {
result = f(result, i, x);
i++;
}
return result;
}
}
}
It creates a generic Aggregate method that also includes an index.
My example (that follows) takes a list of strings and joins the 1st letter from the first word, the 2nd from the second, etc..
namespace ExtensionMethods {
public class Program {
public static string OffsetChars(string x, int i, string y) {
return x + y[i];
}
static void Main(string[] args) {
List<string> test = new List<string>() { "hello", "there", "you" };
// get h from (h)ello, h from t(h)ere and u from yo(u) (hhu)
string result = test.MyAggregate<string, string>(OffsetChars);
Console.WriteLine(result);
Console.ReadKey();
}
}
}
My question is about this line (the important one):
string result = test.MyAggregate<string, string>(OffsetChars);
Without <string, string> there is an error that the types of arguments cannot be inferred from usage. My question(s):
Why cannot they be inferred? Is there something missing from my code that would enable them to be inferred?
I tested with an explicit delegate (follows) but the same error occurs:
namespace ExtensionMethods {
delegate string OffsetMethod(string x, int i, string y);
public class Program {
public static string OffsetChars(string x, int i, string y) {
return x + y[i];
}
static void Main(string[] args) {
List<string> test = new List<string>() { "hello", "there", "you" };
// get h from (h)ello, h from t(h)ere and u from yo(u) (hhu)
OffsetMethod myMethod = OffsetChars;
string result = test.MyAggregate(myMethod);
Console.WriteLine(result);
Console.ReadKey();
}
}
}
To summarize, I want to ensure that I haven't missed anything with my code and, assuming that I haven't, to understand why the parameter types cannot be inferred.
Your method is just a delegate and therefore does not have any generic type arguments that could be infered.
When you define OffsetChars as a generic Func, they can be infered just fine:
public static Func<string, int, string, string> OffsetChars = (x, i, y) =>
{
return x + y[i];
};
WERTZUI is right, because the delegate does not have any generic arguments, compiler cannot infer it, so you have se error.

C# - Passing Delegate as a parameter to a method

I am trying to get familiar with the concept of delegates in C#. I have created this console application so far:
Program.cs
using System;
namespace DelegatesTest
{
class Program
{
static void Main(string[] args)
{
ArithmeticOperation.ArOpDel additionDelegate = new ArithmeticOperation.ArOpDel(ArithmeticOperation.Addition);
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate(10, 5)));
Console.ReadKey();
}
}
}
ArithmeticOperation.cs
using System;
namespace DelegatesTest
{
public static class ArithmeticOperation
{
public delegate int ArOpDel(int x, int y);
public static string ConvertResultToString(ArOpDel del)
{
string result = String.Format("The result of the {0} operation is {1}", del.Method.Name, del.ToString());
return result;
}
public static int Addition(int x, int y)
{
return x + y;
}
public static int Subtraction(int x, int y)
{
return x - y;
}
public static int Multiplication(int x, int y)
{
return x * y;
}
public static int Division(int x, int y)
{
return x / y;
}
}
}
As you can see from the code, I am using a static class called ArithmeticOperation.cs to perform some arithmetic operations. The ConvertResultToString method takes one of the arithmetic operations methods as a parameter in order to display the result elegantly as a string.
Unfortunately, my code does not compile. It is giving me the following error:
Argument '1': cannot convert from 'int' to 'DelegatesTest.ArithmeticOperation.ArOpDel'
The error is being given on this line:
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate(10, 5)));
Can you please help me solve this problem as I am not very experienced with delegates? In fact, I have created this application to learn about delegates.
The additionDelegate(10, 5) will return int by doing arithmetic operation, it will not return deleagate that's the reason of compilation error.
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate(10, 5)));
You are not passing the delegate here. You are calling it, which results in an int.
This would pass the delegate:
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate));
You would need to actually call the delegate somewhere though.
when you do this
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate(10, 5)));
you are forcing the compiler to execute the method and return the result to pass it as an argument which in this case it's an int while the ConvertResultTostring expect a delegate
here how you can get it work without using generic
class Program
{
static void Main(string[] args)
{
ArithmeticOperation.ArOpDel additionDelegate = ArithmeticOperation.Addition;
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate,5,6));
Console.ReadKey();
}
}
public static class ArithmeticOperation
{
public delegate int ArOpDel(int x, int y);
public static string ConvertResultToString(ArOpDel del,int x, int y )
{
string result = String.Format("The result of the {0} operation is {1}", del.Method.Name, del(x,y).ToString());
return result;
}
public static int Addition(int x, int y)
{
return x + y;
}
public static int Subtraction(int x, int y)
{
return x - y;
}
public static int Multiplication(int x, int y)
{
return x * y;
}
public static int Division(int x, int y)
{
return x / y;
}
}
additionDelegate(10, 5) is an invocation of additionDelegate which actually is an Addition function. So, the result is an integer.
In order to pass a delegate you should pass additionDelegate itself instead of additionDelegate(10, 5). But, in this case, the result of the operation will not be available in ConvertResultToString unless you invoke it there.
public static string ConvertResultToString(ArOpDel del)
{
string result = String.Format("The result of the {0} operation is {1}", del.Method.Name, del(10, 5).ToString());
return result;
}
...
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate));
additionDelegate(10, 5) means invoke the delegate,the result is an int type which does not match the ConvertResultToString method stub.
you need change
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate(10, 5)))
to
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate))
and change
string result = String.Format("The result of the {0} operation is {1}", del.Method.Name, del.ToString());
to
string result = String.Format("The result of the {0} operation is {1}", del.Method.Name, del(10,5).ToString());

How can I give the user a possibility to add methods of any type to my dictionary<string,Delegate>?

I need to give the possibility to add any method returning double and taking any amount of double parameters to the Dictionary. Help me please.
class Program
{
Dictionary<string, Delegate> _functions;
static double MyFunc (double x, double y, double z, double q, double r, double t)
{
return 100;
}
// and the user can create his functions with any amount of parameters
static void AddFunction (Delegate d)
{
_functions.Add (d.Method.Name, d);
}
static void Main (string [] args)
{
_functions = new Dictionary<string, Delegate> ();
Program.AddFunction(MyFunc);
}
}
Well, I'm not sure how you plan on exactly calling this. Since you have a variable number of inputs, you can treat them like an array input.
delegate double MyDictionaryDelegate(params double[] input);
static Dictionary<string, MyDictionaryDelegate> _functions;
static void AddFunction (MyDictionaryDelegate d)
{
_functions.Add(d.Method.Name, d);
}
But then this essentially turns your called functions into handling collections (with any of the benefits/limitations this implies):
public static double MyFunc (params double[] input)
{
return input.Sum();
}
So your usage might be like:
_functions = new Dictionary<string, MyDictionaryDelegate> ();
AddFunction(MyFunc);
Console.WriteLine(_functions["MyFunc"](1, 2.5, 0));//3.5
But I suspect you'd rather keep the original list of parameter arguments rather than a list, something like this:
public static double AnotherFunc(double x, double y, double z)
{
return x + y + z;
}
You could simply have a wrapper function:
public static double AnotherFunc(params double[] input)
{
//preferably with some check that the proper number of
//input parameters are included
return AnotherFuncImpl(input[0], input[1], input[2]);
}
But this seems overall kind of dangerous to me; I'm not sure I'd recommend it.
EDIT: Here's another option to avoid the param double[] input arrays and always have fixed parameter arguments. Use the Delegate as you had, but you'd have to use its DynamicInvoke. In addition, you'd declare several AddFunction overloads for each number of parameters you expect to reasonably have:
static Dictionary<string, Delegate> _functions;
private static void AddFunction (string functionName, Delegate d)
{
_functions.Add(functionName, d);
}
private static void AddFunction(Func<double> d)
{
_functions.Add(d.Method.Name, d);
}
private static void AddFunction(Func<double, double> d)
{
_functions.Add(d.Method.Name, d);
}
private static void AddFunction(Func<double, double, double> d)
{
_functions.Add(d.Method.Name, d);
}
private static void AddFunction(Func<double, double, double, double> d)
{
_functions.Add(d.Method.Name, d);
}
//additional overloads up to N parameters
Then usage might be:
public static double MyFunc(double x, double y, double z)
{
return x + y + z;
}
_functions = new Dictionary<string, Delegate> ();
AddFunction(MyFunc);
Console.WriteLine(_functions["MyFunc"].DynamicInvoke(1, 2.5, 0));//3.5
But once again, this can fail if the caller did not properly call DynamicInvoke with the exact number of required parameters (no more, no less).
I still feel as though overall, whatever it is you're doing would benefit from a different design.
Define a new class object that has the delegate and the parameter list you require, then the dictionary<string, clsObject> would be how you define the dictionary.
Cast the method as a Func<T1, T2, .., TResult> when you add it to the collection:
Program.AddFunction(
(Func<double, double, double, double, double, double, double>)MyFunc);
You need to declare your delegate as returning a double, and taking a param of doubles, here is a full working example.
public class Widget
{
// declares a delegate called AddDelegate that takes a param of doubles
public delegate double AddDelegate(params double[] dbls);
Dictionary<string, AddDelegate> functions;
public Widget()
{
functions = new Dictionary<string, AddDelegate>();
}
public void Add(AddDelegate d)
{
functions.Add(d.Method.Name, d);
}
public void Run()
{
foreach (var kvp in functions)
{
// write out the name and result of each function added to our list
Console.Write(kvp.Key);
Console.Write(": ");
Console.Write(kvp.Value(10.0, 10.0, 10.0, 10.0));
}
}
}
class Program
{
static double CalcDouble(params double[] dbls)
{
double total = 0.0;
foreach (double d in dbls)
{
total += d;
}
return total;
}
static void Main(string[] args)
{
var w = new Widget();
w.Add(new Widget.AddDelegate(CalcDouble));
w.Run();
}
}
Do you mean defining a delegate with the params modifier on its arguments? The answer is apparently no, because the compiler converts the additional arguments to an array in a method call, but not for delegates. See the link for some solutions.

Categories