c# - (如何)是否可以绑定(bind)/重新绑定(bind)一个方法来与不同签名的委托(delegate)一起工作?

标签 c# delegates callback signals-slots currying

我是一名 C++ 开发人员,在 C++ 中使用过信号和槽,这对我来说似乎类似于 C# 中的委托(delegate)。我发现自己在寻找“绑定(bind)”提供的功能时不知所措,觉得我一定遗漏了一些东西。

我觉得像下面这样的东西,在 c++ 中是可能的,在带有委托(delegate)的 c# 中应该是可能的。这是我在 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;
}

不幸的是,我无法找到任何关于 c# 委托(delegate)的绑定(bind)/重新绑定(bind)引用。我错过了什么吗?在 C# 中是否有一些完全不同的方法来做到这一点?

最佳答案

在 C# 中我们做这样的事情:

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();
    }
}

很明显,方法 Foo 对应于您的方法 Foo,只是适当调用了 Console.WriteLine 而不是 std::cout

接下来,我们声明一个方法 Curry,它接受一个 Action<T> 并返回一个 Action。通常, Action<T> 是一个接受类型为 T 的单个参数并返回 void 的委托(delegate)。特别地, Foo 是一个 Action<int> 因为它接受一个类型为 int 的参数并返回 void 。至于 Curry 的返回类型,它被声明为 ActionAction 是一个没有参数并返回 void 的委托(delegate)。

Curry 的定义比较有趣。我们正在使用 lambda 表达式定义一个操作,这是一种非常特殊的匿名委托(delegate)形式。有效

() => action(parameter)

表示 void 参数映射到 action,在 parameter 处求值。

最后,在 Main 中,我们声明了一个名为 Actioncurried 实例,它是使用参数 CurryFoo 应用于 5 的结果。这与您的 C++ 示例中的 bind(fun_ptr(foo), 5) 起着相同的作用。

最后,我们通过语法 curried 调用新形成的委托(delegate) curried() 。这就像您示例中的 someCallback()

这个花哨的术语是 currying

作为一个更有趣的示例,请考虑以下内容:

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));
    }
}

这里我们声明了一个方法 Curry 接受一个委托(delegate)( Func<TArg, TArg, TResult> 接受两个相同类型的参数 TArg 并返回一些其他类型的值 TResult 和一个类型为 TArg 的参数并返回一个接受单个参数的委托(delegate)键入 TArg 并返回类型为 TResult ( Func<TArg, TResult> ) 的值。

然后,作为测试,我们声明一个方法 Add,它接受两个类型为 int 的参数并返回一个类型为 int 的参数(一个 Func<int, int, int>)。然后在 Main 中,我们实例化一个名为 addFive 的新委托(delegate),它的作用类似于将输入参数加 5 的方法。因此

Console.WriteLine(addFive(7));

在控制台上打印 12

关于c# - (如何)是否可以绑定(bind)/重新绑定(bind)一个方法来与不同签名的委托(delegate)一起工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2098322/

相关文章:

C# 检查文件夹避免阻塞 UI

javascript - Javascript中的回调机制

c# - 从 WPF 绑定(bind)列表框中删除项目

c# - 检查 C# Action/Lambda/Delegate 是否包含任何代码/语句

c# - 我的 C# 程序被检测为病毒?

xcode - 使用调试器断点在 Xcode 8.1/Swift 3.0 中调用两次委托(delegate)方法

Swift2,在 CFSocketCallBack 中调用 swift 函数 - EXEC_BAD_ACCESS

具有前向声明的 C++ 成员回调

c# - 已接受的用于处理 Excel 数据的集合

c# - Fluent合并到main.exe后出现的问题