2

I am currently reading up on delegates and I wanted to know if there was a way to create a delegate and pass parameters to that delegate during creation.

suppose I have this method

public void test(int a,int b);

Now I can do this

public delegate void DelegateWithParameter(int a,int b);

DelegateWithParameter d = new DelegateWithParameter(test);
d(1,2); //Works

Now how can I create a delegate that has parameters embedded in it so I can simply do this d();?

Also can I pass in partial parameters ? Like pass in second parameter during delegate creation and then pass the first parameter during the use ? I know in C++ we use std::placeholders. I wonder if C# has something like that ?

MistyD
  • 16,373
  • 40
  • 138
  • 240
  • 1
    You can't construct a delegate without a target method, ie. `new DelegateWithParameter()` won't compile, there has to be a method in there. However, let's assume you meant `new DelegateWithParameter(test)`, then you could do this: `Action d = () => test(1, 2);`, and then call `d()` to call `test(1, 2)`. – Lasse V. Karlsen Aug 13 '19 at 10:08
  • Sorry let me fix my code. – MistyD Aug 13 '19 at 10:09
  • To shorten the list of parameters by 1, you just need another delegate that takes just one parameter. Either declare one, or use `Action`, so you could do `Action d = x => test(x, 2);` and then call `d(42)` to call `test(42, 2);`. – Lasse V. Karlsen Aug 13 '19 at 10:09
  • @HimBromBeere, that's not a good duplicate link for this question. – Lasse V. Karlsen Aug 13 '19 at 10:10
  • @HimBromBeere can you tell me how that link compares with std::placeholders::_1 ?? Two different things – MistyD Aug 13 '19 at 10:12
  • @LasseVågsætherKarlsen Indeed, I just remembered on a similar question without reading everything here correctly. – MakePeaceGreatAgain Aug 13 '19 at 10:12
  • 2
    I am pretty sure there is a good candidate here though, just have to find it. – Lasse V. Karlsen Aug 13 '19 at 10:12
  • @LasseVågsætherKarlsen can you expand on your answer please. It looks like an interesting approach. – MistyD Aug 13 '19 at 10:14
  • 1
    You can see an example [here](https://dotnetfiddle.net/53BDfV). – Lasse V. Karlsen Aug 13 '19 at 10:17

2 Answers2

0

Well, if your delegates param-list is that static and you allways provide the same values anyway, why do you even have one? So just use this:

public delegate void DelegateWithParameter();

DelegateWithParameter d = new DelegateWithParameter(() => test(2, 1));
d(); //Works
MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
  • its not static unfortunately. Also I would like to know if its possible ? If so how ? – MistyD Aug 13 '19 at 10:17
  • @MistyD If it´s not static, how should the runtime **ever** know what you mean by `d()`? In the above code you can of course replace `test(2, 1)` by any other call as well, e.g. `test(myInt, anotherInt)`. But be aware on closures here. – MakePeaceGreatAgain Aug 13 '19 at 10:18
  • The method is static. But I would like to know if its possible for a delegate to have partial parameters embedded in it – MistyD Aug 13 '19 at 10:19
  • 1
    Something like this https://en.cppreference.com/w/cpp/utility/functional/placeholders – MistyD Aug 13 '19 at 10:20
  • @MistyD I didn´t refer to the keyword `static`. The above approach works for both, `static` and non-static methods. – MakePeaceGreatAgain Aug 13 '19 at 10:20
  • I understand that. – MistyD Aug 13 '19 at 10:20
  • @MistyD What is still unclear then? You see how to pass a method expecting two numbers into a delegate that expects none. Isn´t that your problem? – MakePeaceGreatAgain Aug 13 '19 at 10:23
0

Basically a delegate is a function signature.

public delegate void DelegateWithParameters(int a, int b);

Your delegate has a signature of a function that accepts 2 ints as parameters and returns void. In order to call a delegate of that type, you have to use two int parameters.

However, you could wrap that delegate in another method, so that you don't have to provide the parameters. Let's say I want to call a delegate above with a default set of parameters. Now I could call that function from anywhere, without specifying parameters for the delegate. (Although they will always be necessary)

public void CallDelegate(DelegateWithParameters method)
{
    method(1, 2);
}

public void Test(int a,int b)
{
    // Do something
}

// Use it like so
CallDelegate(Test);

Or you could have a class with a field containing the delegate for example:

class DelegateInvoker
{
    private DelegateWithParameters method;
    public DelegateInvoker(DelegateWithParameters method)
    {
        this.method = method ?? throw new ArgumentNullException(nameof(method));
    }

    // Note this signature is parameterless
    public void InvokeDelegate()
    {
        // but you do call the delegate with the required parameters
        this.method(1, 2);
    }
}

// Then call it like this
var delegateInvoker = new DelegateInvoker(Test);
delegateInvoker.InvokeDelegate();

A more inline approach would be to create a function on the fly, but it is basically the same thing. You define a new function to wrap the delegate.

DelegateWithParameters method = Test;

// define a new, parameterless method to wrap the delegate
var delegateInvoker = () => method(1, 2);
delegateInvoker();

Lastly, note that the newly created function actually has another signature. So you could define our new function as a delegate like this:

delegate void ParameterlessDelegate();

And the last example could become:

DelegateWithParameters method = Test;

// define a new, parameterless method to wrap the delegate
ParameterlessDelegate delegateInvoker = () => method(1, 2);
delegateInvoker(); 
Jesse de Wit
  • 3,867
  • 1
  • 20
  • 41