(How) is it possible to bind/rebind a method to work with a delegate of a different signature?

c#, callback, currying, delegates, signals-slots

Solution

In C# we do something like this:

class Program {
    static Action Curry<T>(Action<T> action, T parameter) {
        return () => action(parameter);
    }

    static void Foo(int i) {
        Console.WriteLine("Value: {0}", i);
    }
    static void Main(string[] args) {
        Action curried = Curry(Foo, 5);
        curried();
    }
}

Clearly the method `Foo` corresponds to your method `Foo`, just with the appropriate calls to `Console.WriteLine` instead of `std::cout`.

Next, we declare a method `Curry` that accepts an `Action<T>` and returns an `Action`. In general, an `Action<T>` is a delegate that accepts a single parameter of type `T` and returns `void`. In particular, `Foo` is an `Action<int>` because it accepts one parameter of type `int` and returns `void`. As for the return type of `Curry`, it is declared as an `Action`. An `Action` is a delegate the has no parameters and returns `void`.

The definition of `Curry` is rather interesting. We are defining an action using a lambda expression which is a very special form of an anonymous delegate. Effectively

() => action(parameter)

says that the `void` parameter is mapped to `action` evaluated at `parameter`.

Finally, in `Main` we are declaring an instance of `Action` named `curried` that is the result of applying `Curry` to `Foo` with the parameter `5`. This plays the same role as `bind(fun_ptr(foo), 5)` in your C++ example.

Lastly, we invoke the newly formed delegate `curried` via the syntax `curried()`. This is like `someCallback()` in your example.

The fancy term for this is currying.

As a more interesting example, consider the following:

class Program {
    static Func<TArg, TResult> Curry<TArg, TResult>(
        Func<TArg, TArg, TResult> func,
        TArg arg1
    ) {
        return arg => func(arg1, arg);
    }

    static int Add(int x, int y) {
        return x + y;
    }

    static void Main(string[] args) {
        Func<int, int> addFive = Curry<int, int>(Add, 5);
        Console.WriteLine(addFive(7));
    }
}

Here we are declaring a method `Curry` that accepts a delegate (`Func<TArg, TArg, TResult>` that accepts two parameters of the same type `TArg` and returns a value of some other type `TResult` and a parameter of type `TArg` and returns a delegate that accepts a single parameter of type `TArg` and returns a value of type `TResult` (`Func<TArg, TResult>`).

Then, as a test we declare a method `Add` that accepts two parameters of type `int` and returns a parameter of type `int` (a `Func<int, int, int>`). Then in `Main` we instantiate a new delegate named `addFive` that acts like a method that adds five to its input parameter. Thus

Console.WriteLine(addFive(7));

prints `12` on the console.

Problem

I'm a c++ developer having used signals & slots in c++ which to me seems to be analogous to delegates in c#. I've found myself at a loss in searching for the functionality provided by "bind", and feel I must be missing something. I feel like that something like the following, which is possible in c++ should be possible in c# with delegates. Here is some psudo-code for what I would do in c++: ``` Slot<void> someCallback; int foo(int i) { std::cout << "Value: " << i << "\n"; return i; } int main() { int i = 0; Slot<int> someCallback = bind( fun_ptr(foo), i ); ++i; // added to show that late evaluation would be a non-trivial difference int result = someCallback(); assert( result == 0 ); return 0; } ``` Unfortunately, I've not been able to find any reference to binding/rebinding with regards to c# delegates. Am I missing something? Is there some radically different way to do this in c#?

Original source