Generic Attributes and More — Visual Studio Magazine

News

C# 11 Features Preview in Visual Studio: Generic Attributes and More

A new “What’s New in C# 11” post explains the new features available in preview with the latest tools: NET 6.0.200 SDK or Visual Studio 2022 v17.1.

First, support for generic attributes or the ability to create a generic class based on System.Attribute. The Attribute class provides a way to associate information with code declaratively, so that a ObsoleteAttribute indicates code that has been deprecated and should no longer be used, signaling the compiler to look for instances of the attribute and do something corrective in response.

A Microsoft C# 10 documentation for generic attributes (support has been deferred to C# 11) explains the motivation: “Currently, attribute authors can take a System.Type as a parameter and ask users to pass a typeof expression to provide the attribute with the types it needs. However, outside of parsers, there is no way for an attribute author to restrict the types allowed to be passed to an attribute via typeof. If attributes could be generic, then attribute authors could use the existing system of type parameter constraints to express requirements for the types they take as input.”

As the graphic below shows, support for generic attributes is just one of many new features planned for C#:

C# packages
[Click on image for larger view.] C# packages (source: Microsoft).

Support for wildcard attributes was C# expert Jason Bock’s answer to the question, “What C# feature do you wish Microsoft had delivered, but just didn’t come to fruition?” in the September 2021 article “Q&A with Jason Bock: What’s New in C# 10.”

“Generic attributes,” Bock replied. “It’s a capability the CLR has had for a long time, but it’s never been demonstrated in C#. You can define generic attributes in .NET’s intermediate language — IL — and consume them in C#, but you can’t define them directly in C# There are cases where I think this feature would be useful, and I hope it does in C# at some point.

His wishes came true in Visual Studio 17.1, where a developer only has to set click “preview” to enable preview features. Of these, “Allow Wildcard Attributes” has been a long time coming, having been in the works for at least five years.

The new “What’s New in C# 11” documentation just released on March 11 provides more details on its impending manifestation.

“You can declare a generic class whose base class is System.Attribute. This provides a more convenient syntax for attributes that require a System.Type parameter. Previously, you had to create an attribute that takes a Type as a constructor parameter:”

// Before C# 11:
public class TypeAttribute : Attribute
{
  public TypeAttribute(Type t) => ParamType = t;

  public Type ParamType { get; }
}

After using the tyepof operator to apply the attribute, a developer can create a generic attribute and specify the type parameter to use the new functionality. However, some code constructs are not allowed because when a generic attribute is used, it must be completely closed. In other words, it cannot contain any type parameters. Here are some examples :

  • Example 1:

    public class GenericType
        {
          [GenericAttribute()] // Not allowed! generic attributes must be fully constructed types.
          public string Method() => default;
        }
  • Example 2:

    using System;
        using System.Collections.Generic;
        
        public class Attr : Attribute { }
        
        public class Program
        {
          [Attr] // error
          [Attr] // error
          void M() { }
        }>

In addition to explaining the motivation behind the approach, Microsoft also lists a downside of the scheme: “Removing the restriction, analyzing the implications, and adding the appropriate tests is work.”

An alternative is also listed: “Attribute authors who want users to be able to discover the requirements of the types they supply to attributes should write parsers and guide their users to use those parsers in their releases.”

An unresolved question about the diet reads: