(Как) возможно связать/снова переплести метод работать с делегатом другой подписи?

Я - разработчик C++, использовавший сигналы и слоты в C++, чтобы мне, кажется, походит на делегатов в c#. Я нашел меня в недоумении в поиске функциональности предоставленным, "связывают" и чувствуют, что я должен пропускать что-то.

Я чувствую, что что-то как следующее, которое возможно в C++, должно быть возможным в c# с делегатами. Вот некоторый psudo-код для того, что я сделал бы в 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#?

11
задан Catskul 26 January 2010 в 18:48
поделиться

2 ответа

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

четко метод FO соответствует вашему методу foo , просто с соответствующими вызовами Console.writeline вместо STD :: Cout .

Далее мы объявляем метод Curry , который принимает действие и возвращает действие . В целом действие является делегатом, который принимает один параметр типа T и возвращает void . В частности, FOO - это действие , поскольку он принимает один параметр типа int и возвращает void . Что касается возврата типа карри , он объявлен как действие . Действие является делегатом, который не имеет никаких параметров и возврат void .

Определение карри довольно интересно. Мы определяем действие с использованием выражения лямбда, которое является очень особенной формой анонимного делегата. Фактически

() => action(parameter)

говорит, что параметр параметр сопоставлен на действие , оцениваемых в параметра .

Наконец, в Главная Мы объявляем экземпляр действий с именем Curryed , который является результатом применения Curry на Foo с параметром 5 . Это играет одинаковую роль, что и BING (Fun_PTR (FOO), 5) в вашем примере C ++.

Наконец, мы призываем вновь сформированные делегат Curred через синтаксис Curry () . Это похоже на SomeCallback () в вашем примере.

Необработанный термин для этого Carrying .

Как более интересный пример, рассмотрите следующее:

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 и возвращает значение какого-либо другого типа Tresult и параметр типа TARG и возвращает делегат, который принимает один параметр Тип TARG и возвращает значение типа Tresult ( FUNC ).

Затем, как тест, который мы объявляем методом Добавьте , которые принимают два параметра типа INT и возвращает параметр типа int (A функция ). Затем В Главная Мы создали новый делегат имени AddFive , который действует как метод, который добавляет пять к его входному параметру. Таким образом,

Console.WriteLine(addFive(7));

принты 12 на консоли.

15
ответ дан 3 December 2019 в 06:21
поделиться

Чтобы начать вас, вы должны хранить номер в каком-то массиве, как std :: вектор (цифра для каждой позиции в массиве), и вам нужно найти определенный алгоритм, который будет рассчитать факториал (возможно, в какой-то специализированный класс). ;)

-121--2410550-

Попробуйте следующее

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

или для чего-то еще ближе к 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();
  }
}

Объяснение. Здесь происходит то, что я создаю новый делегат с помощью лямбда. Лямбда - это выражение, начиная с () => . В этом случае он создает делегат, принимающий никаких аргументов и не производим никакого значения. Он совместим с действием типа .

4
ответ дан 3 December 2019 в 06:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: