11

我是一名 c++ 开发人员,在 c++ 中使用过信号和插槽,在我看来这类似于 c# 中的委托。我发现自己在搜索“绑定”提供的功能时不知所措,并且觉得我一定遗漏了一些东西。

我觉得像下面这样的东西,在 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# 中是否有一些完全不同的方法可以做到这一点?

4

2 回答 2

15

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

的定义Curry相当有趣。我们正在使用 lambda 表达式定义一个动作,它是匿名委托的一种非常特殊的形式。有效

() => action(parameter)

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

最后,在Main我们声明一个Action名为的实例,curried它是应用参数Curry的结果。这与您的 C++ 示例中的作用相同。Foo5bind(fun_ptr(foo), 5)

curried最后,我们通过语法调用新形成的委托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接受委托的方法(Func<TArg, TArg, TResult>它接受两个相同类型的参数TArg并返回一个其他类型的值TResult和一个类型参数,TArg并返回一个接受单个类型参数TArg并返回一个类型值的委托TResultFunc<TArg, TResult>)。

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

Console.WriteLine(addFive(7));

12在控制台上打印。

于 2010-01-20T00:51:29.530 回答
4

尝试以下

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

于 2010-01-20T00:48:40.610 回答