Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I restrict a custom attribute to void methods only?

I have a custom attribute which I would like to restrict to methods with return type void.

I know I can restrict to methods using [AttributeUsage(AttributeTargets.Method)] but there doesn't seem to be a way to restrict the return type or any other aspect of the methods signature.

The [System.Diagnostics.Conditional] attribute has exactly the kind of limitation I want. Adding it to a non-void method results in the compiler error:

The Conditional attribute is not valid on '(SomeMethod)' because its return type is not void

and IntelliSense says:

Attribute 'System.Diagnostics.ConditionalAttribute' is only valid on attribute classes or methods with 'void' return type.

If I F12 to the ConditionalAttribute I see that it is decorated with the following attributes:

[Serializable]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
[ComVisible(true)]

None of which says anything about the return type.

How is it done for the Conditional attribute and can I do the same for my custom attribute?

like image 909
Roman Reiner Avatar asked May 08 '15 14:05

Roman Reiner


2 Answers

Turns out in my particular case there was a solution since I was using PostSharp.

My custom attribute inherits from PostSharp.Aspects.MethodInterceptionAspect (which inherits from Attribute) which has an overridable CompileTimeValidate(MethodBase method) method.

This allows to emit compiler errors during build time:

public override bool CompileTimeValidate(MethodBase method)
{
    Debug.Assert(method is MethodInfo);
    var methodInfo = (MethodInfo)method;

    if (methodInfo.ReturnType != typeof(void))
    {
        Message.Write(
            method, SeverityType.Error, "CX0001",
            "The Foo attribute is not valid on '{0}' because its return type is not void",
            method.Name);

        return false;
    }

    return true;
}
like image 89
Roman Reiner Avatar answered Nov 20 '22 22:11

Roman Reiner


Most attributes are simply metadata that gets attached to classes and that can be examined at runtime. However, some attributes are used by the compiler. System.ObsoleteAttribute for example can be used to have the compiler emit errors or warnings if the method, class etc is used. System.Diagnostics.ConditionalAttribute is another example of an attribute used by the compiler. As such, the compiler itself is free to impose rules on its use that cannot be applied to other attributes (such as void methods only).

Unfortunately, at this time, it's not possible to affect the compiler though custom attributes. With Rosalyn being written in C#, the way is then opened up to have the compiler run code within the attribute as part of the compilation phase. Your example of restriction an attribute to void methods would be one such use of this feature, if it were implemented.

like image 26
David Arno Avatar answered Nov 20 '22 21:11

David Arno