CLSCompliant
.NET
C#
Common Language Specification
programming attributes

What is the 'CLSCompliant' attribute in .NET?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The CLSCompliant attribute tells .NET compilers whether publicly exposed code follows the Common Language Specification, or CLS. That matters when you are writing a library that should be usable from multiple .NET languages, not just from C#.

What the CLS Is Trying to Solve

The .NET runtime supports many languages, but not every language supports every .NET feature in the same way. The CLS defines a common subset that all CLS-aware languages are expected to understand.

For example, C# supports unsigned integers such as uint, but some other .NET languages historically did not expose them cleanly. If a public API uses types that fall outside the CLS, consumers in those languages may see awkward bindings or may not be able to call the API at all.

The attribute exists to make that mismatch visible during compilation.

Apply It at the Assembly Level

The most common usage is at assembly scope:

csharp
using System;

[assembly: CLSCompliant(true)]

With that declaration, the compiler warns you when a public type or member violates CLS rules. That is useful for library code because it turns interoperability issues into ordinary build feedback instead of letting them become consumer surprises later.

What a Violation Looks Like

Unsigned public members are the classic example:

csharp
1using System;
2
3[assembly: CLSCompliant(true)]
4
5public class Counter
6{
7    public uint NextValue()
8    {
9        return 42;
10    }
11}

This typically produces a compiler warning because uint is not CLS-compliant for a public API. The code still compiles, but the warning tells you the method is not broadly language-friendly.

A CLS-friendly version would expose a signed type instead:

csharp
1using System;
2
3[assembly: CLSCompliant(true)]
4
5public class Counter
6{
7    public int NextValue()
8    {
9        return 42;
10    }
11}

The point is not that uint is wrong in general. The point is that it is a poor choice when public interoperability across .NET languages is a goal.

Override Compliance for Specific Members

Sometimes most of an assembly is intended to be CLS-compliant, but one member is deliberately not. You can mark that member explicitly:

csharp
1using System;
2
3[assembly: CLSCompliant(true)]
4
5public class NativeInterop
6{
7    [CLSCompliant(false)]
8    public uint ReadFlags()
9    {
10        return 7;
11    }
12}

This tells consumers and the compiler that the noncompliant API is intentional. It also prevents the assembly-level setting from generating the same warning for that member over and over.

When It Matters and When It Does Not

CLSCompliant matters most for reusable libraries, SDKs, plugins, and frameworks. If other teams may consume your assembly from VB.NET, F#, PowerShell, or a code generator, CLS-aware public APIs are safer.

It matters much less for application code where C# calls only C# inside one solution. In that case, exposing a uint or another non-CLS type may be perfectly reasonable because there is no real cross-language audience.

This is why many modern internal applications ignore CLS compliance entirely, while public framework libraries still care about it.

Internal Members Are Different

The attribute is mainly about the public surface area. Internal implementation details can use whatever types make sense because outside languages do not consume them directly.

That distinction is important. Developers sometimes start rewriting internal code to satisfy CLS rules even though the compiler warning only matters for what escapes the assembly boundary.

Common Pitfalls

  • Treating CLSCompliant(true) as a runtime behavior switch is incorrect; it is metadata and compiler guidance, not an execution feature.
  • Assuming that all .NET types are automatically CLS-compliant leads to surprising warnings once an assembly-level attribute is added.
  • Applying the attribute only to a member while forgetting the assembly-level intent makes library policy harder to understand.
  • Rewriting internal code to satisfy CLS rules usually adds noise without improving interoperability, because CLS concerns are mostly about public APIs.
  • Ignoring warnings on a public library means cross-language consumers may hit awkward or unsupported member signatures later.

Summary

  • 'CLSCompliant marks whether public .NET APIs follow the Common Language Specification.'
  • It is mainly used on library code that should work across multiple .NET languages.
  • Assembly-level CLSCompliant(true) asks the compiler to warn about noncompliant public members.
  • Member-level CLSCompliant(false) is the normal escape hatch when a specific API must use a non-CLS type.

Course illustration
Course illustration

All Rights Reserved.