(如何)是否可以绑定/重新绑定一个方法以与不同签名的委托一起使用?

发布于 2024-08-18 14:55:50 字数 641 浏览 9 评论 0原文

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

我觉得像下面这样的东西,在 c++ 中是可能的,在带有委托的 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# 委托的绑定/重新绑定的参考。我错过了什么吗?在 C# 中是否有一些完全不同的方法来做到这一点?

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#?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

雨落星ぅ辰 2024-08-25 14:55:50

在 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 并返回 Action。一般来说,Action 是接受 T 类型的单个参数并返回 void 的委托。特别是,Foo 是一个 Action,因为它接受一个 int 类型的参数并返回 void。至于Curry的返回类型,它被声明为ActionAction 是一个委托,没有参数并返回 void

Curry 的定义相当有趣。我们使用 lambda 表达式定义一个操作,这是一种非常特殊的匿名委托形式。实际上

() => action(parameter)

表示 void 参数映射到在 parameter 处计算的 action

最后,在 Main 中,我们声明一个名为 curriedAction 实例,它是将 Curry 应用到 < code>Foo 与参数 5。这与 C++ 示例中的 bind(fun_ptr(foo), 5) 的作用相同。

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

对此的奇特术语是柯里化

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

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

这里我们声明了一个接受委托的方法 CurryFunc 接受两个参数)相同类型 TArg 并返回某种其他类型 TResult 的值和类型 TArg 的参数,并返回接受单个类型参数的委托TArg 并返回一个 TResult 类型的值(Func)。

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

Console.WriteLine(addFive(7));

打印 12 。控制台。

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.

久光 2024-08-25 14:55:50

尝试以下

class Example {
  static void foo(int i) {
    Console.WriteLine(i);
  }
  public static void Main() {
    Action someCallback = () => foo(5);
    someCallback();
  }
}

或者更接近 C++ 对应部分的

class Example {
  static void foo(int i) {
    Console.WriteLine(i);
  }
  static Action bind<T>(Action<T> action, T value) {
    return () => action(value);
  }
  public static void Main() {
    Action someCallback = bind(foo, 5);
    someCallback();
  }
}

解释。这里发生的是我通过 lambda 表达式创建一个新的委托。 lambda 是以 () => 开头的表达式。在这种情况下,它创建一个不接受任何参数且不产生任何值的委托。它与 Action 类型兼容。

Try the following

class Example {
  static void foo(int i) {
    Console.WriteLine(i);
  }
  public static void Main() {
    Action someCallback = () => foo(5);
    someCallback();
  }
}

Or for something even closer to the C++ counter part

class Example {
  static void foo(int i) {
    Console.WriteLine(i);
  }
  static Action bind<T>(Action<T> action, T value) {
    return () => action(value);
  }
  public static void Main() {
    Action someCallback = bind(foo, 5);
    someCallback();
  }
}

Explanation. What's happening here is that I am creating a new delegate by means of a lambda expression. The lambda is the expression starting with () =>. In this case it creates a delegate accepting no arguments and producing no value. It is compatible with the type Action.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文