Marking API's as obsolete or as experimental


Often times your API in your program or library evolves. So you will need a mechanism for telling that a specific API (an interface or just a simple method call) is obsolete and might be not there anymore in the next major version.

Also, it can happen that you have a preview version of an API, which might not be rock-stable and the API-surface might change. How do we indicate that to the user?

The simple answer: Attributes. .NET knows two special ones in this case:

  • ObsoleteAttribute
  • RequiresPreviewFeaturesAttribute

They are a bit special.


The ObsoleteAttribute is in the Framework since almost the beginning. It marks that the element should not be used anymore. The attribute is special because the compiler knows of it and treats it in a certain way. Here is a quick example of how to use it:

OldWarning(); // Generates warning (or error if you enable treat warnings as errors)
OldError(); // Generates errors

[Obsolete($"Take {nameof(New)} instead", false)]
void OldWarning() { }

[Obsolete($"Take {nameof(New)} instead", true)]
void OldError() { }

void New() { }

The first argument is a message to a user, which you can use to indicate, which new method he should use instead. The second one is about whether or not the compiler should treat it as a warning (which is the default, if you don't provide that parameter) or even as an error. The compiler tells you the following: "CS0618: Local function 'OldWarning()' is obsolete: Take New instead".

So you can make a 3 step approach:

  1. Mark it as warning
  2. Mark it as error
  3. Remove it entirely

By the way the attribute can also be set on a class, property, interface or struct. You are not limited to use it on methods.


The RequiresPreviewFeaturesAttribute is used to indicate that a feature is in a preview state. Feature can mean a simple method or a whole class or interface. The usage is roughly the same:


[RequiresPreviewFeatures("API might change")]
void New() { }

If you hover over the New() call you get the message: "API might change". If you try to compile that, you get even an error: "Program.cs(1, 1): [CA2252] API might change Using 'New' requires opting into preview features. See for more information."

The resolve that you have to opt-in into preview features. This is done on project level:

<Project Sdk="Microsoft.NET.Sdk">


        <!-- This will opt in into all preview features -->

Unfortunately it isn't very fine grained. You don't have control over which features you want to use. The (maybe ugly) alternative is using pragmas:

#pragma warning disable CA2252
#pragma warning restore CA2252

In any way, this is until now (.net 7) the only way of marking an API as a preview. In contrast to the ObsoleteAttribute, which is handled by the compiler, the RequiresPreviewFeaturesAttribute is handled via Roslyn-Analyzer.


I showed you a way of marking your APIs as old so you can delete them gracefully later and I also showed you how to mark them as experimental so your user knows, that the API surface is not stable.

Free .NET 8 Web API Live Stream's

It's time to stream some ASP.NET 8 Web API Content! For free - just because why not!

In this blog post you will find the details!

Reusable loading Bar Component in Blazor

In our Blazor components we often call a repository or web API which takes some time. So it is nice to indicate to an user what the current state is. That is why we will create a small indicator even with steps to indicate how far we are in the progress.

Fluent API to await multiple calls and get their respective results

Sometimes, you have multiple async calls to make, and you want to do that asynchronously and get the results afterward. Let's build a fluent API to do that.

An error has occurred. This application may no longer respond until reloaded. Reload x