Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would an empty delegate event handler cause a CA1061 warning?

Update: This occurs when the Code Analysis option "Suppress results from generated code (managed only)" is turned off, and Rule Set is set to "Microsoft Basic Design Guideline Rules".

On 2013-04-26, Microsoft confirmed this is a bug, but will not fix it in either this or the next version of Visual Studio.

Link to MS Connect item

We frequently initialize event handlers with an empty delegate to avoid the need for checking nulls. E.g.:

public EventHandler SomeEvent = delegate {};

However, since starting to compile some of our code in Visual Studio 2012 (RTM), I'm noticing a lot of events in derived classes are now triggering CA1601: Do not hide base class methods warnings in Visual Studio 2012's Code Analysis.

Here's a sample that will trigger the warning:

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;
    }
}

Note: In VS2012 the warning is triggered when compiled in either .NET 4.5 or .NET 4.0. The same sample does not trigger the warning in VS2010.

Performance reasons aside, are there any legitimate reasons we shouldn't be initializing events with empty delegates? The default assumption is that it's probably just a quirk in the analysis in Visual Studio 2012.

Here's the code analysis result for those that don't have access to VS2012 yet:

CA1061 Do not hide base class methods Change or remove 'Class2.Class2()' because it hides a more specific base class method: 'Class1.Class1()'. TestLibrary1 Class1.cs 14

Addendum: I found that the option to "Suppress results from generated code" in the code analysis is turned off.

Also, I found that this seems to occur when the event handler in the base type is both:

  • a delegate other than EventHandler or EventHandler -and-
  • events in both the base class and the derived class are initialized using an anonymous method or empty delegate (either inline or in the constructor).

Of possible relevance: We're running Visual Studio 2012 RTM, which was installed in-place over the release candidate.

like image 434
Sean Avatar asked Aug 16 '12 19:08

Sean


People also ask

What is a delegate event handler?

The EventHandler delegate is a predefined delegate that specifically represents an event handler method for an event that does not generate data. If your event does generate data, you must use the generic EventHandler<TEventArgs> delegate class.

Can we use events without delegates?

Yes, you can declare an event without declaring a delegate by using Action.

How are delegates used in event handling?

A delegate is a way of telling C# which method to call when an event is triggered. For example, if you click a Button on a form, the program would call a specific method. It is this pointer that is a delegate. Delegates are good, as you can notify several methods that an event has occurred, if you wish so.

What is the difference between an event and an EventHandler?

In programming, an event handler is a callback routine that operates asynchronously once an event takes place. It dictates the action that follows the event. The programmer writes a code for this action to take place. An event is an action that takes place when a user interacts with a program.


1 Answers

The problem is the C# compiler generates a static delegate used to initialize your instance delegate, which is named the same for both Class1 and Class2.

Class1.CS$<>9__CachedAnonymousMethodDelegate1 exists for use by Class1's constructor to initialize PropertyCancelled, while Class2.CS$<>9__CachedAnonymousMethodDelegate1_ exists for use by Class2's constructor to initialize SelectionCancelled.

It's unfortunate that the C# compiler doesn't include some sort of record of the parent class' auto-generated 'stuff' when deciding how to name auto-generated 'stuff' for a child class. Crack this open in ILDasm and the issue becomes immediately obvious. Good to know that you found a work around. The warning is completely reasonable to ignore, given that you can't touch the static delegates from C#, thanks to non-C#-compliant naming.

like image 152
Kevin Frei Avatar answered Sep 25 '22 04:09

Kevin Frei