C# Constant Naming Conventions: PascalCase, Not ALL_CAPS (.NET 10)

Our code reviews still catch MAX_CART_ITEMS in new C# code, usually from developers who came from Java, Python or C.

Quick answer: the C# constant naming convention is PascalCase for every const, whether it’s public, private or local, with no underscore prefix:

public const int MaxCartItems = 50;         // not MAX_CART_ITEMS
private const int ReturnWindowDays = 30;    // not _returnWindowDays
const int FreeShippingItems = 3;            // local constant, same rule

I tested this in a .NET 10 checkout for a Texas outdoor store, then made the build flag your bad names.

What You Need Before You Start with C# Constant Names

  • The .NET 10 SDK. Each example is a file-based app you run with dotnet run File.cs.
  • VS Code with the C# Dev Kit (see how to create a console application in Visual Studio Code).
  • The sample: checkout code for Lone Star Trail Outfitters, a made-up outdoor store in Austin, Texas.

This post covers constants only. For classes, methods, properties and the rest, start with our naming conventions in C# overview.

Step 1: Name const Fields and Local Constants in PascalCase

Microsoft’s C# coding conventions use PascalCase for constant fields and local constants, including private and internal ones. Here’s the store’s checkout with all three:

const int FreeShippingItems = 3;          // local constant
int itemsInCart = 2;

Console.WriteLine($"Max cart size: {Checkout.MaxCartItems}");
Console.WriteLine($"Currency: {Checkout.CurrencyCode}");
Console.WriteLine($"Add {FreeShippingItems - itemsInCart} more for free shipping");

static class Checkout
{
    public const int MaxCartItems = 50;
    public const string CurrencyCode = "USD";
    private const int ReturnWindowDays = 30;
    public static string ReturnPolicy => $"{ReturnWindowDays}-day returns";
}

Output:

Max cart size: 50
Currency: USD
Add 1 more for free shipping
C# constant naming convention: public, private and local const names in PascalCase in VS Code with the dotnet run output
Every constant is PascalCase, whatever its access level

A shopper with two items is one short of free shipping. A local constant like FreeShippingItems skips the camelCase rule that variables in C# follow, and I like that: you can tell at a glance the value can’t change.

Why Not ALL_CAPS for C# Constants?

SCREAMING_CASE compiles, because the compiler doesn’t enforce naming conventions. It just doesn’t match .NET itself. Ask reflection which built-in fields are real constants:

using System.Reflection;

FieldInfo[] fields =
[
    typeof(int).GetField(nameof(int.MaxValue))!,
    typeof(TimeSpan).GetField(nameof(TimeSpan.TicksPerDay))!,
    typeof(Math).GetField(nameof(Math.PI))!,
    typeof(DateTime).GetField(nameof(DateTime.MaxValue))!,
    typeof(string).GetField(nameof(string.Empty))!,
];
foreach (FieldInfo f in fields)
    Console.WriteLine($"{f.DeclaringType!.Name + "." + f.Name,-20} const: {f.IsLiteral}");

Output:

Int32.MaxValue       const: True
TimeSpan.TicksPerDay const: True
Math.PI              const: True
DateTime.MaxValue    const: False
String.Empty         const: False
Built-in .NET constants int.MaxValue, TimeSpan.TicksPerDay and Math.PI are PascalCase const fields, checked with FieldInfo.IsLiteral in VS Code
int.MaxValue, TimeSpan.TicksPerDay and Math.PI are const; DateTime.MaxValue and string.Empty are static readonly

Three are true const fields, and all five are PascalCase. Math.PI is all caps only because the Framework Design Guidelines capitalize two-letter acronyms, like IOStream.

The same guidelines say not to use underscores in identifiers, so MAX_CART_ITEMS breaks two rules. Our C# variable naming conventions guide lists the casing for everything else.

Step 2: Name a private const Without an Underscore

This is the rule I see broken most. In the .NET runtime style, private fields start with _ and private static fields with s_, but constants don’t, because a constant isn’t a field you can change.

var cart = new CartService("Lone Star Trail Outfitters");
cart.Add(3);
cart.Add(2);
Console.WriteLine(cart.Summary());

class CartService(string storeName)
{
    private const int MaxCartItems = 50;              // const: PascalCase, no _
    private static int s_cartsOpened;                 // static: s_camelCase
    private readonly string _storeName = storeName;   // field: _camelCase
    private readonly int _cartNumber = ++s_cartsOpened;
    private int _itemCount;

    public void Add(int quantity) => _itemCount += quantity;
    public string Summary() =>
        $"{_storeName} cart #{_cartNumber}: {_itemCount}/{MaxCartItems} items";
}

Output:

Lone Star Trail Outfitters cart #1: 5/50 items
C# private const MaxCartItems in PascalCase next to s_cartsOpened and _storeName private fields in VS Code
Same class, three naming styles: the const has no prefix

The s_ prefix is a runtime team convention, not the Visual Studio default. Our C# fields naming conventions post compares it with plain _camelCase.

Step 3: Use static readonly Instead of const for Values That Change

Microsoft Learn warns against const for prices, version numbers or brand names, because compilers copy a constant’s value into every assembly that uses it. Change it later and those assemblies keep the old value until they’re rebuilt.

Texas’s 6.25% state sales tax rate can change, so our store keeps it in a static readonly field. The name stays PascalCase:

using System.Globalization;
CultureInfo.CurrentCulture = new("en-US");

decimal subtotal = 189.97m;
decimal tax = Math.Round(subtotal * StorePolicy.TexasSalesTaxRate, 2);
Console.WriteLine($"Subtotal {subtotal:C}, state tax {tax:C}");
Console.WriteLine($"Price list: {StorePolicy.PriceListDate:yyyy-MM-dd}");
Console.WriteLine($"Cart limit: {StorePolicy.MaxCartItems} items");

static class StorePolicy
{
    public const int MaxCartItems = 50;                          // fixed for good
    public static readonly decimal TexasSalesTaxRate = 0.0625m;  // can change
    public static readonly DateOnly PriceListDate = new(2026, 11, 1);
}

Output:

Subtotal $189.97, state tax $11.87
Price list: 2026-11-01
Cart limit: 50 items

A $189.97 order gets $11.87 of state tax. static readonly also covers types that can’t be constant. A const must be a number, bool, char, string, enum or null (see data types in C#), so const DateOnly fails with CS0283.

Public static readonly fields use PascalCase, like DateTime.MaxValue; private ones follow your field rule (s_cartTimeout).

Step 4: Group Shared Constants in a Static Class like ApiDefaults

When several files need the same values, we put them in one static class. Same store, now its order API:

Console.WriteLine(ApiDefaults.OrdersRoute);
Console.WriteLine($"Timeout: {ApiDefaults.TimeoutSeconds}s");
Console.WriteLine(Describe(429));

static string Describe(int status) => status switch
{
    ApiDefaults.TooManyRequests => $"Rate limited, retry {ApiDefaults.MaxRetries}x",
    _ => "OK",
};

static class ApiDefaults
{
    public const string BaseRoute = "/api/v1";
    public const string OrdersRoute = $"{BaseRoute}/orders";
    public const int TimeoutSeconds = 30;
    public const int MaxRetries = 3;
    public const int TooManyRequests = 429;
}

Output:

/api/v1/orders
Timeout: 30s
Rate limited, retry 3x
C# constants grouped in a static class ApiDefaults with an interpolated const string and a const in a switch pattern, in VS Code
OrdersRoute is built from BaseRoute at compile time

OrdersRoute is a constant interpolated string, which works when every part is a constant string. Constants also work as patterns in a switch case in C#, which a static readonly field can’t do.

Name the class by the C# class naming conventions: ApiDefaults, not API_DEFAULTS.

Step 5: Enforce Constant Names with .editorconfig and IDE1006

Code reviews miss things, so we let the build check names. Put this .editorconfig in your project or repo root:

root = true

[*.cs]
# Report naming problems in the build, not only in the editor
dotnet_diagnostic.IDE1006.severity = warning
dotnet_diagnostic.CA1707.severity = warning
dotnet_code_quality.CA1707.api_surface = all

# Constants (fields and locals, any access level): PascalCase
dotnet_naming_symbols.constants.applicable_kinds = field, local
dotnet_naming_symbols.constants.applicable_accessibilities = *
dotnet_naming_symbols.constants.required_modifiers = const
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_rule.constants_are_pascal_case.symbols = constants
dotnet_naming_rule.constants_are_pascal_case.style = pascal_case
dotnet_naming_rule.constants_are_pascal_case.severity = warning

# Private static fields: s_camelCase
dotnet_naming_symbols.private_static_fields.applicable_kinds = field
dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private
dotnet_naming_symbols.private_static_fields.required_modifiers = static
dotnet_naming_style.s_camel_case.capitalization = camel_case
dotnet_naming_style.s_camel_case.required_prefix = s_
dotnet_naming_rule.private_static_fields_are_s_camel.symbols = private_static_fields
dotnet_naming_rule.private_static_fields_are_s_camel.style = s_camel_case
dotnet_naming_rule.private_static_fields_are_s_camel.severity = warning

# Private instance fields: _camelCase
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
dotnet_naming_style.underscore_camel_case.capitalization = camel_case
dotnet_naming_style.underscore_camel_case.required_prefix = _
dotnet_naming_rule.private_fields_are_underscore_camel.symbols = private_fields
dotnet_naming_rule.private_fields_are_underscore_camel.style = underscore_camel_case
dotnet_naming_rule.private_fields_are_underscore_camel.severity = warning

A naming rule’s own severity only shows in the IDE. For dotnet build warnings, set dotnet_diagnostic.IDE1006.severity and turn on EnforceCodeStyleInBuild, which the #:property line does in a .NET 10 file-based app. I packed every mistake into one file:

#:property EnforceCodeStyleInBuild=true

const int maxRetries = 3;
const int MAX_TIMEOUT = 30;
var cart = new CartService();
Console.WriteLine($"Limit: {cart.Limit}, retries: {maxRetries}, timeout: {MAX_TIMEOUT}");

public class CartService
{
    public const int MAX_CART_ITEMS = 50;
    private const int _maxQuantity = 10;
    private const int MaxDiscountPercent = 25;
    private static readonly TimeSpan CartTimeout = TimeSpan.FromMinutes(20);
    private int itemCount = 0;
    public int Limit => MAX_CART_ITEMS - _maxQuantity - MaxDiscountPercent
                        + itemCount - CartTimeout.Minutes;
}

dotnet build NamingCheck.cs –no-incremental -v q -nologo:

C:\DotNetDemo\ConstNamingDemo\NamingCheck.cs(10,22): warning CA1707: Remove the underscores from member name CartService.MAX_CART_ITEMS (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)
C:\DotNetDemo\ConstNamingDemo\NamingCheck.cs(13,38): warning IDE1006: Naming rule violation: Missing prefix: 's_' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1006)
C:\DotNetDemo\ConstNamingDemo\NamingCheck.cs(14,17): warning IDE1006: Naming rule violation: Missing prefix: '_' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1006)
C:\DotNetDemo\ConstNamingDemo\NamingCheck.cs(3,11): warning IDE1006: Naming rule violation: These words must begin with upper case characters: maxRetries (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1006)
C:\DotNetDemo\ConstNamingDemo\NamingCheck.cs(11,23): warning CA1707: Remove the underscores from member name CartService._maxQuantity (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)
C:\DotNetDemo\ConstNamingDemo\NamingCheck.cs(11,23): warning IDE1006: Naming rule violation: Prefix '_' is not expected (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1006)
C# constant naming enforced with .editorconfig: IDE1006 and CA1707 warnings for maxRetries, MAX_CART_ITEMS and _maxQuantity in the VS Code terminal
IDE1006 and CA1707 flag five names; MAX_TIMEOUT gets through

Important: pascal_case only checks the first letter, so the local MAX_TIMEOUT passed. CA1707 caught MAX_CART_ITEMS, but it skips locals, so you still need a reviewer for those.

MaxDiscountPercent passed too, so the const rule beat the s_ rule for private constants.

C# Constant Naming Cheat Sheet

What you’re namingConventionExample
public const fieldPascalCaseMaxCartItems
private / internal constPascalCase, no prefixReturnWindowDays
Local constantPascalCaseFreeShippingItems
public static readonlyPascalCaseTexasSalesTaxRate
private static readonlys_camelCase (runtime style)s_cartTimeout
Class of constantsPascalCase nounApiDefaults
Two-letter acronymBoth letters upperMath.PI, IOTimeout

Team Rules for Naming Constants in C#

These go straight into our coding standard, and you can copy them into yours:

  • PascalCase for every const, with no _, k or c_ prefix.
  • Name the meaning, not the value: MaxCartItems, never Fifty. Boolean constants read like boolean variable names: IsTaxExempt.
  • const only for values that never change; static readonly for rates, dates, prices and versions.
  • One static class per area (ApiDefaults, StorePolicy), and the .editorconfig above in the repo root.

Common Mistakes to Avoid with C# Constant Names

MistakeWhat happensFix
MAX_CART_ITEMSCA1707 warning, looks foreign next to .NET APIsMaxCartItems
private const int _maxQuantityIDE1006: prefix ‘_’ is not expectedMaxQuantity
const int maxRetries (local)IDE1006: must begin with upper caseMaxRetries
A tax rate as public constOther assemblies keep the old valuestatic readonly
const DateOnlyCS0283, the type can’t be conststatic readonly DateOnly

Next Steps

Enum members follow the same PascalCase rule, with a few extra rules for singular and flags names. Our C# enum naming conventions guide is the natural next read.

We’d pair these with this post too:

Frequently Asked Questions

Should C# constants be uppercase?

No. Use PascalCase, like MaxCartItems. ALL_CAPS compiles, but it doesn’t match .NET’s own constants such as int.MaxValue, and CA1707 flags the underscores.

How do you name a private const in C#?

PascalCase with no prefix: private const int MaxQuantity = 10;. The _ and s_ prefixes are only for non-constant fields.

Are local constants PascalCase in C#?

Yes, even though ordinary local variables are camelCase.

What’s the naming convention for static readonly fields?

Public ones are PascalCase, like DateTime.MaxValue. Private ones follow your field rule, s_camelCase in the .NET runtime style.

How do I enforce constant naming in a C# project?

Add naming rules to .editorconfig, set IDE1006 to warning and turn on EnforceCodeStyleInBuild. The syntax is in Code-style naming rules on Microsoft Learn.