Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build warnings for Obsolete C# events

Does anyone know of a trick or workaround to get the Visual Studio C# compiler to issue build warnings when an Obsolete event is being used?

If I create a simple assembly with a public event and apply the Obsolete attribute to the event, when I reference that assembly and subscribe to the event in another project, the compiler does not issue a warning when I build (even with the highest warning level or warnings set to errors).

Declaration of event in Project 1:

    public class APIClass
    {
        [Obsolete("Obsolete in v2.0")]
        public event EventHandler ObsoleteEvent;
    }

Use of Obsolete event in Project 2 does not cause a build warning:

    private void SubscribeToEvent(APIClass apiClass)
    {
        apiClass.ObsoleteEvent += delegate { };
    }

When I open the source file, Visual Studio recognizes the event as Obsolete and adds the warning (or error) to the Error List: Background source processing recognizes the warning

However, as soon as I build, the warning disappears and does not appear in the build output: The warning is gone after compiling

The missing compiler warning seems to have been filed as a bug, but until it is fixed, is there any possible way to force a warning when someone uses the event? Otherwise there is no way to alert external consumers that they need to change their calling code.

like image 935
Origameg Avatar asked Dec 05 '12 10:12

Origameg


People also ask

Is C# warning obsolete?

The Obsolete Attribute marks elements like classes, methods, properties, fields, delegates, and many others within our code as deprecated or obsolete. The attribute is read at compile time and it is used to generate a warning or an error to the developer.

Why is it a good idea to always enable compiler warnings in C?

A compiler warning signals a potentially serious problem in your code. The problems listed above are almost always fatal; others may or may not be, but you want compilation to fail even if it turns out to be a false alarm. Investigate each warning, find the root cause, and fix it.

What are warnings C++?

Compiler warnings are messages produced by a compiler regarding program code fragments to be considered by the developer, as they may contain errors. Unlike compilation errors, warnings don't interrupt the compilation process.


1 Answers

It does seem to be an acknowledged bug, but I can think of a work around which I hope will work for your situation.

The event keyword is only a syntatical shortcut for a multicast delegate that conforms to specific signature, and exposes itself neatly in a similar manner to a property. One solution you could try is to make the event private, and expose a method for adding listeners which you in turn mark as obsolete:

public class APIClass
{
    [Obsolete("Obsolete in v2.0")]
    private event EventHandler ObsoleteEvent;

    [Obsolete("Obsolete in v2.0")]
    public void AddListener(EventHandler eh)
    {
        ObsoleteEvent += eh;
    }

}

private static void SubscribeToEvent(APIClass apiClass)
{
    //apiClass.ObsoleteEvent += delegate { };
    apiClass.AddListener(delegate { });
}

I hope this work around works for you! Best of luck!

* edit *

To further illustrate why this is a bug, allow me to show you the MSIL generated by this code. Following the analogy of the event keyword behaving like the property keyword, it emits a "add_ObsoleteEvent" and a "remove_ObsoleteEvent" method. You don't see them in your editor but they are how the code is linked together.

This is the add method that is created. Notice that the 'Obsolete' attribute is not added to the compiler generated method?

.method private hidebysig specialname instance void 
        add_ObsoleteEvent(class [mscorlib]System.EventHandler 'value') cil managed
{
  // Code size       48 (0x30)
  .maxstack  3

/// rest omitted

This is contrasted by the "AddListener" method we wrote, to which we manually added the 'Obsolete' attribute. Notice that the compiler has added the 'Obsolete' attribute to the method?

.method public hidebysig instance void  AddListener(class [mscorlib]System.EventHandler eh) cil     managed
{
  .custom instance void [mscorlib]System.ObsoleteAttribute::.ctor(string) = ( 01 00 10 4F 62 73     6F 6C 65 74 65 20 69 6E 20 76   // ...Obsolete in v
                                                                              32 2E 30 00 00 )                                      // 2.0..
  // Code size       10 (0xa)
  .maxstack  8

/// rest omitted.

To make this emit a warning at compile time away from the editor, it may be possible to manually add this to the MSIL. I haven't tried this so I can't say whether it would work or not. But I thought I would make this edit to demonstrate why the problem is occuring. I hope it helps!

like image 118
LED Avatar answered Sep 29 '22 08:09

LED