Почему я не могу вызвать BeginInvoke непосредственно для метода, вместо того, чтобы назначать его делегату? - PullRequest
1 голос
/ 21 июня 2010

Я просто смотрю на часть своего кода, и мне пришло в голову, что дано:

      Action<int> fireMessage = FireMessages;
      fireMessage.BeginInvoke(1, r => fireMessage.EndInvoke(r), null);

Поскольку я могу напрямую назначить метод делегату, почему могу 'Я просто вызываю метод BeginInvoke напрямую.То, как этот код читает, предполагает, что назначение делегата является избыточным.

Но вызов BeginInvoke непосредственно для метода вызывает исключение компилятора.

Ответы [ 4 ]

2 голосов
/ 21 июня 2010

Метод не является делегатом - делегат - это отдельный тип, который ссылается на метод - на самом деле в делегате больше информации, чем просто метод.

Технически, для компилятора может быть возможно подключить это для вас и сократить ввод текста, но я на самом деле несколько благодарен, что это не было сделано. Вынуждая вас назначить делегата для ссылки на метод объекта, а затем вызывать его с помощью BeginInvoke, компилятор заставляет вас быть более явным по вашему желанию.

Вызов делегата через BeginInvoke потенциально может иметь некоторые серьезные побочные эффекты - это должно быть явное, целенаправленное действие. Многие методы не будут работать должным образом, если они будут вызываться в отдельных потоках, и, по крайней мере, таким образом, вам нужно знать, что вы делаете, чтобы работать таким образом.

Как говорится, в .NET 4 я бы порекомендовал изменить способ «запуска методов» в «фоновых потоках». Вместо использования Delegate.BeginInvoke я бы рекомендовал рассмотреть возможность перехода на использование нового класса Task:

Task.Factory.StartNew( () => FireMessages(1) );

У новой библиотеки задач есть много преимуществ, особенно когда речь идет об обработке ошибок, отмене, предотвращении переподписки в пуле потоков и т. Д.

1 голос
/ 21 июня 2010

Здесь есть немного синтаксического сахара. Делегат действительно скрыт от объекта, который оборачивает ваш метод, и в нем определен метод BeginInvoke. Синтаксический сахар заключается в том, что вы можете назначить «метод» делегату (без явного создания делегата), но он работает только в этом контексте.

0 голосов
/ 26 февраля 2013

Компилятор может автоматически создать делегат из группы методов, если ему известен тип создаваемого делегата.Однако он не может вывести тип делегата на основе группы методов, потому что разные типы делегатов, как правило, несовместимы, даже если подписи совпадают.Хотя существует много ситуаций, когда компилятор может фактически использовать любой делегат с определенной сигнатурой, у компилятора нет возможности узнать, что это за ситуации.Следовательно, группы методов неявно преобразуются в делегаты только в тех случаях, когда компилятор может идентифицировать тип делегата другими способами.

0 голосов
/ 21 июня 2010

Я думаю, что это дизайн. В C # методы не являются объектами, как в функциональных языках, но делегаты.

Конструктор делегата - это «точка касания», поддерживаемая компилятором C #, и это единственное место, где метод используется в качестве «ссылки на метод» вместо «вызова метода».

Доступ к объекту «экземпляр метода экземпляра» с использованием someInstance.Method.SomeMethodOfMethod имеет запутанный синтаксис и требует наличия экземпляра метода. Некоторые могут ожидать, что экземпляры методов, полученные из одного и того же метода одного и того же объекта, также должны быть одинаковыми, и для этого потребуется дополнительное использование памяти для хранения экземпляра метода внутри объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...