0

I want to pass a function as a parameter to another function (with actual values) and later execute it. Here is JavaScript code:

function functionToPass1 (x,y) {
    console.log(x, y);
}

function functionToPass2 (x,y,z) {
    console.log(x, y, z);
}

function mainFunction(param1, param2, functionToPass){
  console.log(param1, param2);
  functionToPass();

}

mainFunction("a", "b", function(){
    functionToPass2(1, 2, 3) ;
});

How to write this in C# (or VB.Net)?

Dejan Dozet
  • 948
  • 10
  • 26
  • 1
    If the function takes two string parameters and returns an int, you can pass it as parameter of type `Func myfunc` and invoke it as `a = myfunc(s1, s2);` [C# syntax]. See e.g. here: https://stackoverflow.com/questions/3624731/what-is-func-how-and-when-is-it-used – Klaus Gütter Jul 24 '22 at 17:50
  • 1
    And here for VB.net: https://stackoverflow.com/questions/17469541/func-vs-function-in-vb – Klaus Gütter Jul 24 '22 at 17:51

3 Answers3

4

Func<> Delegates are what you are looking for to pass methods in another method. I wrote a small example below, you can apply it according to your needs. Func<> is a generic delegate. It can be Func<int,string> Func<int,int,bool> and so on. The last one represents the return type and the others represent the input parameter types of method.

static void Main(string[] args)
{
    MethodB(MethodA);
    Console.ReadLine();
}

static string MethodA(string message) //Func<string,string>
{
    return message;
}

static void MethodB(Func<string, string> method)
{  
    Console.WriteLine(method("I am MethodA"));
}

For more detailed information, you can check this link => https://www.tutorialsteacher.com/csharp/csharp-func-delegate

Jussi Palo
  • 848
  • 9
  • 26
ABI
  • 191
  • 4
  • Now I need to set that string message in the first call in Main, something like methodb(methoda ("message")) is that possible? – Dejan Dozet Jul 24 '22 at 18:05
  • You can write directly `method("I am MethodA");`, no need for `method.Invoke("I am MethodA");` (the `.Invoke()` part, I mean) – Jimi Jul 24 '22 at 18:20
  • You can use lambda like this MethodB(x => x = "I am a new method"); but this is not MethodA. This is just another method – ABI Jul 24 '22 at 18:22
  • 1
    `method?.Invoke(...)` is preferred in case `method` is null. – Eric J. Jul 24 '22 at 18:25
  • Sometimes it's difficult to emphasize what one is trying to do, I want to pass both function and arguments to another and invoke it there, in all examples here and there only function is passed, for now I think that JavaScript is capable of such thing – Dejan Dozet Jul 24 '22 at 18:32
  • Actually, I exactly understand what you want to achieve but as far as I know, we can't do that. Because when you define a Func delegate you can't get the arguments of MethodA. – ABI Jul 24 '22 at 18:40
  • You just pass a method so that you can use it in Method B. This should be how the callback function works. Therefore, you shouldn't be able to do what you want to achieve even with javascript. For example, when we write MethodB(x => "I am a new method") , x represents the input parameter of Func and "I am a new method" represents the return type. I mean Func<... , string>. You need to define how to use x in MethodB – ABI Jul 24 '22 at 18:40
1

Thank you all for contributing, your help meant all to me. The only thing I needed to figure out that is an anonymous function to be passed. C# equivalent is like this:

string functionToPass1(int i, string x, string y)
{
  return string.Join(',', new[] { i.ToString(), x, y });
}

string functionToPass2(int i, string x, string y, string z)
{
  return string.Join(',', new[] { i.ToString(), x, y, z });
}

string mainFunction(string param1, string param2, Func<int,string>? functionToPass)
{
  Console.WriteLine(param1);
  Console.WriteLine(param2);
  var res = "";
  int i = 5;
  if (functionToPass != null)
    res = functionToPass(i);
  return res;
}

var res = "";

res = mainFunction("a", "b", (x) =>
{
  return functionToPass2(x, "1", "2", "3");
});

Console.WriteLine(res);
Console.WriteLine("---------------");

res = mainFunction("a", "b", (x) =>
{
  return functionToPass1(x, "1", "2");
});

Console.WriteLine(res);
Console.WriteLine("---------------");

res = mainFunction("a", "b", null);

Console.WriteLine(res);
Console.WriteLine("---------------");
Console.ReadLine();
Dejan Dozet
  • 948
  • 10
  • 26
1

I didn't delete the first comment in case it might be useful to other people in the future. I made some changes for the code you refreshed. I tried to create a generic structure as much as possible. However, Javascript is much more flexible than C#. In other words, even if the structure is generic, at some points we have to break this genericity.

        static void Main(string[] args)
        {
            MainFunction<string, string, int>("a", "b", FunctionToPass2<int, int, int>);
            Console.ReadLine();
        }

        static void FunctionToPass1<T1, T2>(T1 x, T2 y) 
        {
            Console.WriteLine(x + " " + y);
        }

        static void FunctionToPass2<T1, T2, T3>(T1 x, T2 y, T3 z)
        {
            Console.WriteLine(x + " " + y + " " + z);
        }

        static void MainFunction<T1, T2, T3>(T1 param1, T2 param2, Action<T3, T3, T3> functionToPass)
        {
            Console.WriteLine(param1 + " " + param2 + "\n");
            FunctionToPass2(1, 2, 3);
        }

If our parameter types are certain, I believe we will come up with a much simpler solution by not writing it generic. For example, I assume that T3 for Action<T3, T3, T3> delegate is int for this solution because your arguments are integer. Here we have to break the 'generic' structure a bit.

ABI
  • 191
  • 4
  • I was struggling to get a more generic way, so I can pass functions with different numbers of arguments + I need to change some parameters inside MainFunction and then (x) =>{return functionToPass1(x, "1", "2");} came so handy to me. It is actually SPOT ON! Can I ask you to upwote my question I think it deserves a positive zero at least :) – Dejan Dozet Jul 24 '22 at 21:14
  • Of course:) you are right:) – ABI Jul 24 '22 at 21:21
  • Thanks ABI I appreciate your effort on this, I think that someone may find this thread useful and helpful and that we did good job on it – Dejan Dozet Jul 24 '22 at 21:25