News

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

A new "What's new in C# 11" post explains new features available in preview with the latest tooling bits: NET 6.0.200 SDK or Visual Studio 2022 v17.1.

First on tap is generic attributes support, or the ability to create a generic class based on System.Attribute. The Attribute class provides a way of associating information with code in a declarative way, such that an ObsoleteAttribute indicates code that is obsolete and shouldn't be used anymore, signaling the compiler to look for instances of the attribute and do something corrective in response.

Some C# 10 Microsoft documentation for generic attributes (support was postponed to C# 11) explains the motivation: "Currently attribute authors can take a System.Type as a parameter and have users pass a typeof expression to provide the attribute with types that it needs. However, outside of analyzers, there's no way for an attribute author to constrain what types are 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 the requirements for the types they take as input."

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

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

Generic attribute support was the answer C# expert Jason Bock provided when asked "What's a C# feature that you wish Microsoft would come out with, but it just hasn't materialized?" in the September 2021 article "Q&A with Jason Bock: What's New in C# 10."

"Generic attributes," Bock replied. "This is a capability that the CLR has had for a long time, but it's never been surfaced in C#. You can define generic attributes in the intermediate language of .NET -- IL -- and consume them in C#, but you can't define them in C# directly. There are cases where I think this feature would be useful, and I'm hoping it makes it into C# at some point."

His wishes have come true in Visual Studio 17.1, where a developer need only set <LangVersion> to "preview" to enable preview features. Among those, "Allow Generic Attributes" has been a long time coming, in the works for at least five years.

New "What's new in C# 11" documentation just published 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'd need to create an attribute that takes a Type as its 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 feature. However, certain code constructs aren't allowed because when a generic attribute is used, it needs to be fully closed. In other words, it can't contain any type parameters. Here are a couple examples:

  • Example 1:
    public class GenericType<T>
        {
          [GenericAttribute<T>()] // Not allowed! generic attributes must be fully constructed types.
          public string Method() => default;
        }
  • Example 2:
    using System;
        using System.Collections.Generic;
        
        public class Attr<T1> : Attribute { }
        
        public class Program<T2>
        {
          [Attr<T2>] // error
          [Attr] // error
          void M() { }
        }

In addition to explaining the motivation behind the approach, Microsoft also lists a drawback of the scheme: "Removing the restriction, reasoning out 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 for the types they provide to attributes need to write analyzers and guide their users to use those analyzers in their builds."

An unresolved question about the scheme reads:

  • [x] What does AllowMultiple = false mean on a generic attribute? If we have [Attr<string>] and [Attr<object>] both used on a symbol, does that mean "multiple" of the attribute are in use?
  • For now we are inclined to take the more restrictive route here and consider the attribute class's original definition when deciding whether multiple of it have been applied. In other words, [Attr<string>] and [Attr<object>] applied together is incompatible with AllowMultiple = false.

The March 11 announcement also notes that type arguments must satisfy the same restrictions as the typeof operator, and it lists some disallowed metadata annotations.

The post also details static abstract members in interfaces, a runtime preview feature that is also available by this setting: <EnablePreviewFeatures>True</EnablePreviewFeatures>.

"You can add static abstract members in interfaces to define interfaces that include overloadable operators, other static members, and static properties," Microsoft said. "The primary scenario for this feature is to use mathematical operators in generic types." More on that is available in the tutorial titled "Explore static abstract interface members."

While developer attitudes toward generic attributes seem to be mostly positive, judging by GitHub comments, other C# 11 preview features that Microsoft has discussed drew much developer ire, especially parameter null checking. Read more about that in the article, "Devs Sound Off on C# 11 Preview Features Like Parameter Null Checking."

About the Author

David Ramel is an editor and writer at Converge 360.

comments powered by Disqus

Featured

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube