Почему пустой обработчик события делегирования вызывает предупреждение CA1061?
Обновление: Это происходит, когда параметр "Анализ кода" "Подавление результатов сгенерированного кода (только управляемый)" отключен, а в наборе правил установлено "Основные правила разработки Microsoft Basic".
В 2013-04-26 Microsoft подтвердила, что это ошибка, но не исправляет ее ни в этой, ни в следующей версии Visual Studio.
Ссылка на элемент MS Connect
Мы часто инициализируем обработчики событий пустым делегатом, чтобы избежать необходимости проверки нулей. Например:.
public EventHandler SomeEvent = delegate {};
Однако, начиная с компиляции некоторых из нашего кода в Visual Studio 2012 (окончательная первоначальная версия), я замечаю, что многие события в производных классах теперь запускаются CA1601: не скрывать методы базового класса в Visual Code 2012 Code Analysis.
Здесь образец, который вызовет предупреждение:
using System;
using System.ComponentModel;
[assembly: CLSCompliant( true )]
namespace TestLibrary1
{
public abstract class Class1
{
public event PropertyChangedEventHandler PropertyChanged = delegate {};
}
public class Class2 : Class1
{
// this will cause a CA1061 warning
public event EventHandler SelectionCancelled = delegate { };
}
public class Class3 : Class1
{
// this will not cause a CA1061 warning
public event EventHandler SelectionCancelled;
}
}
Примечание. В VS2012 предупреждение запускается при компиляции в .NET 4.5 или .NET 4.0. Тот же образец не вызывает предупреждение в VS2010.
Отклонения в производительности, Есть ли какие-либо законные причины, по которым мы не должны инициализировать события с пустыми делегатами? По умолчанию предполагается, что это, вероятно, просто причуда в анализе в Visual Studio 2012.
Здесь результат анализа кода для тех, у кого еще нет доступа к VS2012:
CA1061 Не скрывать методы базового класса. Измените или удалите "Class2.Class2()", потому что он скрывает более конкретный метод базового класса: "Class1.Class1()". TestLibrary1 Class1.cs 14
Добавление: Я обнаружил, что опция "Подавлять результаты сгенерированного кода" в анализе кода отключена.
Кроме того, я обнаружил, что это происходит, когда обработчик событий в базовом типе:
- делегат, отличный от EventHandler или EventHandler, и
- события как в базовом классе, так и в производном классе инициализируются с использованием анонимного метода или пустого делегата (либо встроенного, либо в конструкторе).
Возможная релевантность: мы запускаем RTM Visual Studio 2012, который был установлен на месте над кандидатом на выпуск.
Ответы
Ответ 1
Проблема заключается в том, что компилятор С# генерирует статический делегат, используемый для инициализации вашего делегата экземпляра, который называется одинаковым для Class1 и Class2.
Class1.CS$<>9__CachedAnonymousMethodDelegate1
существует для использования конструктором Class1 для инициализации PropertyCancelled
, тогда как Class2.CS$<>9__CachedAnonymousMethodDelegate1_
существует для использования конструктором Class2 для инициализации SelectionCancelled
.
Несчастливо, что компилятор С# не включает какую-то запись родительского класса "автоматически сгенерированный материал" при принятии решения о том, как назвать автоматически сгенерированный "материал" для дочернего класса. Взломайте это в ILDasm, и проблема сразу станет очевидной. Приятно знать, что вы нашли работу. Предупреждение вполне разумно игнорировать, учитывая, что вы не можете прикасаться к статическим делегатам из С#, благодаря неигровому именованию, отличному от С#.