When I declare a public event in a sealed C++/CLI class, I get Code Analysis warning CA1047. The warning seems to come from auto-generated protected member functions. How can I fix this warning?
Here's an example. This code
ref class Test sealed {
public:
event EventHandler^ blah;
};
generates:
warning: CA1047 : Microsoft.Design : Make member 'Test::blah::raise(Object^, EventArgs^)' private, public, or internal
I'll document the question better. This code
ref class Test sealed {
public:
event EventHandler^ blah;
};
generates:
warning: CA1047 : Microsoft.Design : Make member 'Test::blah::raise(Object^, EventArgs^)' private, public, or internal
Yes, when you don't specify the event accessors yourself then the compiler will generate them for you. It auto-generates the add, remove and raise accessors. The latter one looks like this when you look with ildasm.exe:
.method family hidebysig specialname instance void
raise_blah(object value0,
class [mscorlib]System.EventArgs value1) cil managed
{
// etc..
}
The family attribute is what causes the code analysis warning. The auto-generated add and remove accessors are of course public. Writing them yourself is a questionable workaround, you really only want to do this if you have a real reason to implement custom accessors. The boilerplate version would look like this:
using namespace System::Runtime::CompilerServices;
ref class Test sealed {
private:
EventHandler^ foo;
public:
event EventHandler^ blah {
[MethodImpl(MethodImplOptions::Synchronized)]
void add(EventHandler^ d) { foo += d; }
[MethodImpl(MethodImplOptions::Synchronized)]
void remove(EventHandler^ d) { foo -= d; }
private:
void raise(Object^ sender, EventArgs^ e) {
EventHandler^ handler = foo;
if (handler != nullptr) handler(sender, e);
};
}
};
Well, that certainly suppresses the warning. I recommend you use the [SuppressMessage] attribute if that doesn't spin your propeller.