Передача анонимного делегата в поток... почему это работает?

В моей программе мы разделили большой объем данных, которые необходимо просмотреть по четырем потокам.

Thread one = new Thread(delegate() { NewMethod(recordsSplitIntoQuarters[0], param2, param3, param4, param5); });
Thread two = new Thread(delegate() { NewMethod(recordsSplitIntoQuarters[1], param2, param3, param4, param5); });
Thread three = new Thread(delegate() { NewMethod(recordsSplitIntoQuarters[2], param2, param3, param4, param5); });
Thread four= new Thread(delegate() { NewMethod(recordsSplitIntoQuarters[3], param2, param3, param4, param5); });

Наши стандарты кодирования требуют, чтобы мы были как бы совместимы с StyleCop, а StyleCop требует следующего:

SA1410: удалить скобки из анонимного метода, поскольку список параметров делегата пуст.

Это дает мне ошибку компилятора:

Вызов неоднозначен между следующими методами или свойствами: 'System.Threading.Thread.Thread(System.Threading.ParameterizedThreadStart)' и 'System.Threading.Thread.Thread(System.Threading.ThreadStart)'

Я изучил объекты ThreadStart и ParameterizedThreadStart и просто не могу понять, как получить то, что мне нужно, с любым из этих объектов.

Мой вопрос: как работают анонимные делегаты? К чему они сводятся? В конце концов, мне придется заставить это работать без анонимных делегатов, но я не знаю, с чего начать.

Спасибо за помощь,

Искатель

3 ответа

Решение

У вас есть два варианта:

  • Игнорировать предупреждение StyleCop (рекомендуется)
  • Измените это на new ThreadStart(delegate { ... })

Объяснение:

Анонимный метод без скобок (delegate { ... }) имеет список неявных параметров. Компилятор предоставит ему любые параметры, необходимые для соответствия делегату, в котором он используется. (Ваш код не может видеть параметры)
Это очень полезно при написании анонимных обработчиков событий, которые не используют свои параметры; это спасает вас от набора текста delegate(object sender, EventArgs e) { ... },

Однако при вызове Thread Конструктор, есть две разные перегрузки, которые принимают два вида делегатов.
Компилятор не может узнать, какой тип делегата вы пытаетесь создать, поскольку вы не указали список параметров.

StyleCop отсталый.

StyleCop подразумевает, что оба синтаксиса имеют одинаковое значение. Это совершенно неправильно. Пропуск скобок от делегата не означает "это не требует аргументов". Это означает "приведите какие-либо аргументы для меня, потому что я все равно не буду их использовать".

Поскольку две разные подписи Thread:.ctor доступны, каждый из которых принимает свой тип делегата, компилятор не может знать, какой из них выбрать, так как с любым из них все будет в порядке. Добавление скобок заставляет компилятор выбрать ThreadStart вариант, так как это единственная подпись с типом делегата, совместимым с вашим анонимным методом.

Если вы хотите порадовать StyleCop и скомпилировать код, это один из вариантов:

Thread one = new Thread(new ThreadStart(delegate { NewMethod(recordsSplitIntoQuarters[0], param2, param3, param4, param5); }));

Это другое:

Thread one = new Thread((ThreadStart) delegate { NewMethod(recordsSplitIntoQuarters[0], param2, param3, param4, param5); });

Но я бы предложил LART авторам StyleCop ввести это нелепое правило.

Вы можете использовать лямбда-выражение вместо delegate ключевое слово:

Thread one = new Thread(() => NewMethod(recordsSplitIntoQuarters[0], param2, param3, param4, param5));
Другие вопросы по тегам