C#12 ExperimentalAttribute: Schöne Idee — aber wer schreibt bei euch wirklich Libraries?

Maarten Balliauw erklärt das neue ExperimentalAttribute in C#12 sauber und präzise. Was ich als KMU-Berater ergänze: Für wen das wirklich relevant ist — und für wen nicht.

⚙ KI-Entwurf Dieser Beitrag wurde automatisiert generiert und nicht redaktionell freigegeben. Behandelt ihn entsprechend.

Letzten Herbst saß ich bei einem Maschinenbauer in der Nähe von Stuttgart. Acht Entwickler, internes ERP auf .NET-Basis, seit 15 Jahren gewachsen. Der Teamlead zeigte mir stolz ihre interne NuGet-Struktur: fünf Pakete, sauber getrennt, versioniert. Ich fragte: „Wer konsumiert diese Pakete außer euch?" Pause. „Na ja, eigentlich nur wir." Dann, nach kurzem Nachdenken: „Und manchmal das Schwesterunternehmen in Österreich."

Das ist der Normalfall in 80 % der KMUs, die ich sehe. Kein öffentliches Ökosystem, keine Community, die man informieren muss. Trotzdem war die Frage wichtig — denn genau da entscheidet sich, ob ein Feature wie das neue ExperimentalAttribute in C#12 für euch Werkzeug oder Zierde ist.


Was Maarten Balliauw beschreibt

Balliauw erklärt in seinem Artikel, wie man in C#12 mit [Experimental("DIAGID")] eine API explizit als experimentell markieren kann — sodass der Build standardmäßig mit einem Fehler abbricht, wenn jemand diese Methode verwendet. Der Konsument muss aktiv opt-in, indem er die Warnung via <NoWarn> im Projektfile oder per #pragma unterdrückt. Zusätzlich kann man eine UrlFormat-URL mitgeben, die im Build-Log erscheint und auf Dokumentation verweist. Für ältere .NET-Versionen zeigt er, dass man [Obsolete] mit DiagnosticId als Workaround nutzen kann — und verweist auf das Polyfill-Projekt von Simon Cropp für noch ältere Targets.

Der Artikel ist technisch korrekt, gut geschrieben, und kommt mit einem echten Praxisbeispiel aus dem JetBrains Space SDK. Genau da liegt auch der implizite Kontext: Balliauw schreibt Libraries, die tatsächlich von anderen Teams oder Organisationen konsumiert werden.


Wie das in einem KMU mit 30–300 Mitarbeitenden landet

Ehrliche Antwort: Bei den meisten meiner Mandate ist ExperimentalAttribute das falsche Instrument — nicht weil es schlecht ist, sondern weil das zugrundeliegende Problem anders aussieht.

Szenario 1: Ihr habt eine interne Library, die nur euer Team nutzt.

In diesem Fall löst ihr das Problem schon mit einem Team-Meeting, einem ADR (Architecture Decision Record) im Wiki, oder schlicht einem Kommentar im Code. Der Build-Fehler schützt euch vor — wem genau? Vor euch selbst? Das ist Overhead ohne Mehrwert. Ich hab das in drei Projekten gesehen, wo jemand [Experimental] eingeführt hat, ohne dass je jemand anderes die Library konsumiert hat. Nach sechs Monaten wurde der Attribute still und heimlich wieder entfernt, weil er nur Konfusion erzeugte.

Szenario 2: Ihr habt ein Schwesterunternehmen oder eine externe Partnerentwicklung, die eure Pakete nutzt.

Jetzt wird es interessant. Hier fängt der Attribute an, Sinn zu ergeben — aber nur, wenn ihr auch einen Prozess dahinter habt. Ein Build-Fehler allein hilft nichts, wenn das andere Team trotzdem <NoWarn>SPC101</NoWarn> in ihre Projektdatei schreibt, weil der Build rot ist und sie Deadline haben. Was ich in der Praxis empfehle: Kombiniert das mit einem echten Changelog-Prozess. Der UrlFormat-Parameter von Balliauw ist hier der unterschätzte Teil — eine URL, die ins Confluence oder die interne Docs-Seite zeigt, macht den Unterschied zwischen „Build-Fehler weggeklickt" und „Entwickler versteht, was auf ihn zukommt".

Szenario 3: Ihr baut tatsächlich öffentliche oder semi-öffentliche Libraries.

Dann ist das Feature Pflicht, nicht Kür. Klare Empfehlung: Sofort einführen, für alles, was noch nicht API-stabil ist. Der Break-by-default-Ansatz (statt Warnung) ist dabei der entscheidende Fortschritt gegenüber [Obsolete]. Warnungen werden ignoriert. Fehler nicht.


Was im Artikel fehlt — aus KMU-Sicht

Balliauw ist Library-Autor bei JetBrains. Er denkt in Ökosystemen. Was er nicht adressiert — und was ich in der Beratung ständig sehe — ist die soziale Komponente dieser Entscheidung.

Ein [Experimental]-Attribute setzt voraus, dass ihr euch organisatorisch darüber einig seid, was "experimentell" bedeutet. In Teams unter 15 Entwicklern passiert das oft nicht explizit. Ich hab Codebases gesehen, wo Methoden seit zwei Jahren [Experimental] waren — längst produktiv genutzt, längst stabil, aber niemand hat sich getraut, den Attribute zu entfernen, weil das eine bewusste Entscheidung gewesen wäre, die keiner treffen wollte.

Das zweite, was fehlt: Wann hebt ihr den experimentellen Status auf? Ein Kriterium wie „nach zwei Releases ohne Breaking Change wird der Attribute entfernt" ist einfach, klar, und verhindert, dass experimental zur dauerhaften Ausrede wird. Sowas gehört ins Team-Agreement, nicht in den Code.

Und drittens — das ist mein persönlicher Schmerzpunkt — fehlt die Diskussion über Granularität. Ich sehe zu oft, dass ganze Klassen oder sogar Namespaces als experimental markiert werden, weil man sich nicht entscheiden wollte. Das führt dazu, dass in einem Package 60 % aller Methoden experimental sind. An dem Punkt hat der Attribute keine Aussagekraft mehr.


Meine konkrete Empfehlung

Wenn ihr in .NET entwickelt und interne Libraries habt, die von mehr als einem Team genutzt werden:

  1. Nutzt [Experimental] — aber nur für Methoden, bei denen ihr konkret wisst, dass ihr die Signatur noch ändern werdet. Nicht als catch-all für "wir sind noch nicht sicher".
  2. Hängt immer eine UrlFormat-URL rein, die auf echte Dokumentation zeigt. Kein Link = die Warnung wird blind weggeklickt.
  3. Legt im Team fest, nach welchem Kriterium ihr den Attribute entfernt. Ohne Exit-Kriterium ist experimental ein Dauerzustand.
  4. Für interne Monorepos ohne externe Konsumenten: Spart euch den Overhead und nutzt stattdessen Code-Reviews und explizite Naming-Konventionen (*Experimental, *Draft) für instabile Bereiche.
  5. Für ältere .NET-Targets (< .NET 6): Der [Obsolete]-Workaround mit DiagnosticId funktioniert, ist aber optisch irreführend. Das Polyfill-Projekt von Simon Cropp, das Balliauw erwähnt, ist in dem Fall die sauberere Lösung — prüft es kurz, bevor ihr euch mit dem Workaround abfindet.

Das Feature ist gut. Es löst ein echtes Problem. Aber in KMU-Kontexten ist das echte Problem meist nicht "wie kommuniziere ich API-Instabilität", sondern "haben wir überhaupt einen Prozess, der über den Build hinausgeht". Der Attribute ist nur so stark wie der Prozess dahinter.


Der vollständige Original-Beitrag von Maarten Balliauw: Provide opt-in to experimental APIs using C#12 ExperimentalAttribute


Habt ihr das in eurer Codebase schon eingesetzt — und wie hat euer Team damit umgegangen? Oder habt ihr noch keine klare Linie, wo "experimentell" anfängt und aufhört? Dann reden wir kurz darüber, was in eurer Situation tatsächlich hilft.

30 Min Klartext-Sparring

— Bernhard