C# Reserved Keywords
Level: Beginner to Intermediate
Goal: Know what C# keywords do and when to use them - reference guide.
Keywords are words C# has reserved. You cannot use them as variable names.
Examples:
int class = 5; // ERROR: class is a keyword
int student = 5; // OK: student is not a keyword
This article catalogues all 79 keywords.
When You'll Use This in SMS
SMS code uses keywords throughout:
public class Student { }
public interface IRepository { }
public abstract class BaseEntity { }
int age = 25;
string name = "Sahasra";
bool isActive = true;
public static class Constants { }
private readonly string _id;
protected virtual void Process() { }
foreach (var student in students)
{
if (student.IsActive)
switch (student.ClassName) { case "10th": break; }
}
await ProcessStudentsAsync();
if (obj is Student student)
Console.WriteLine(student.Name);
C# keywords explained: all 79 categorized, escaping with @, real SMS usage. Video coming soon. Subscribe to NexCoding YouTube for updates.
- All 79 C# reserved keywords organized by category
- Type keywords (bool, int, string, void, dynamic)
- Declaration keywords (class, interface, enum, record)
- Access modifiers (public, private, protected, internal)
- Modifier keywords (static, readonly, const, abstract, virtual, sealed)
- Control flow keywords (if, for, foreach, while, switch, try, catch)
- Object keywords (new, this, base, null, typeof, nameof)
- Type checking keywords (is, as)
- Parameter modifiers (ref, out, in, params)
- Async keywords (async, await)
- LINQ query keywords
- Contextual keywords (var, yield, get, set)
- When to use
@to escape keywords
C# has 79 reserved keywords - identifiers the compiler treats specially. You cannot use them as variable names unless prefixed with @. This article is a complete reference.
Type Keywords
bool // true/false - System.Boolean
byte // 0-255 - System.Byte
sbyte // -128-127 - System.SByte
char // Unicode - System.Char
short // -32768 to 32767 - System.Int16
ushort // 0-65535 - System.UInt16
int // -2B to 2B - System.Int32
uint // 0-4B - System.UInt32
long // large int - System.Int64
ulong // large uint - System.UInt64
float // 7 digits - System.Single
double // 15-17 digits - System.Double
decimal // 28-29 digits - System.Decimal (use for money)
string // text - System.String
object // base of all types - System.Object
void // no return value
dynamic // type resolved at runtime
Declaration Keywords
class // reference type blueprint
struct // value type blueprint
interface // contract with no implementation
enum // named integer constants
record // immutable reference type (C# 9+)
delegate // type-safe method reference
event // delegate-based notification
namespace // group related types
using // import namespace / resource management
// Examples
public class Student { }
public struct Point { }
public interface IGradable { }
public enum Grade { A, B, C, D, F }
public record ExamResult(int Marks, string Subject);
public delegate void NotifyHandler(string msg);
Access Modifier Keywords
public // accessible everywhere
private // same class only
protected // same class + derived classes
internal // same assembly (project)
// Combined
protected internal // same assembly OR derived
private protected // same assembly AND derived (C# 7.2)
Modifier Keywords
static // belongs to type, not instance
readonly // set once (in constructor or initializer)
const // compile-time constant
abstract // must be overridden in derived class
virtual // can be overridden
override // overrides virtual/abstract member
sealed // prevents further inheritance/override
new // hides base class member (or creates object)
partial // split class/method across files
extern // implemented outside C# (P/Invoke)
volatile // field accessed by multiple threads - no optimization
unsafe // unsafe context for pointers
Control Flow Keywords
if / else // conditional branching
switch / case / default // multi-branch on value
for // count-based loop
foreach / in // iterate collection
while // condition-based loop
do // executes at least once
break // exit loop/switch
continue // skip to next iteration
return // exit method, return value
goto // jump to label (avoid)
// Examples
for (int i = 0; i < 10; i++) { }
foreach (var s in students) { }
while (condition) { }
do { } while (condition);
Exception Handling Keywords
try // block to monitor for exceptions
catch // handle exception
finally // always executes
throw // raise exception
// Example
try
{
var student = students.First(s => s.Id == id);
}
catch (InvalidOperationException ex)
{
throw new StudentNotFoundException(id);
}
finally
{
Console.WriteLine("Search complete.");
}
Object Keywords
new // create object instance
this // reference current instance
base // reference base class
null // no reference / no value
true / false // boolean literals
typeof // get Type object at compile time
sizeof // get size of value type in bytes (unsafe context)
nameof // get name of symbol as string
default // default value of type
// typeof - get Type at compile time
Type t = typeof(Student);
Console.WriteLine(t.Name); // "Student"
// nameof - refactor-safe string
public void SetName(string name)
{
ArgumentNullException.ThrowIfNull(name, nameof(name));
// "name" string literal updates automatically if param renamed
}
// default - default value
int zero = default; // 0
string empty = default; // null
bool falsy = default; // false
Student none = default; // null
// sizeof - in unsafe context
unsafe
{
Console.WriteLine(sizeof(int)); // 4 bytes
Console.WriteLine(sizeof(double)); // 8 bytes
Console.WriteLine(sizeof(char)); // 2 bytes
}
Type Checking Keywords
is // check type / pattern match
as // safe cast - returns null if fails
// is - type check + pattern variable
object member = new Student { Name = "Sahasra", Percentage = 87.5 };
if (member is Student student)
Console.WriteLine($"Student: {student.Name}");
if (member is Student { Percentage: >= 90 }) // property pattern
Console.WriteLine("Top student");
// as - safe cast
Student? s = member as Student; // null if not Student
if (s != null)
Console.WriteLine(s.Name);
// vs hard cast - throws InvalidCastException if fails
var s2 = (Student)member; // throws if wrong type
Checked / Unchecked - Overflow Control
// Default - overflow silently wraps around (unchecked)
int max = int.MaxValue; // 2147483647
int wrapped = max + 1; // -2147483648 (silent overflow!)
// checked - throws OverflowException
try
{
int result = checked(max + 1);
}
catch (OverflowException)
{
Console.WriteLine("Overflow detected!");
}
// checked block
checked
{
int marks = int.MaxValue;
int bonus = marks + 1; // throws OverflowException
}
// unchecked - explicit, suppress overflow check
unchecked
{
int wrapped2 = int.MaxValue + 1; // -2147483648, no exception
}
// School Management use case - total marks calculation
static int SafeTotalMarks(int[] marks)
{
int total = 0;
checked // catch any overflow in marks calculation
{
foreach (int m in marks)
total += m;
}
return total;
}
Parameter Modifier Keywords
ref // pass by reference - caller's variable modified
out // output parameter - method MUST assign
in // read-only reference - no copy, no modification
params // variable number of arguments
// Examples
static void Swap(ref int a, ref int b) { int t = a; a = b; b = t; }
static bool TryParse(string s, out int result) { /* ... */ }
static double GetPercentageFast(in ExamResult r) { /* read only */ }
static int Total(params int[] marks) => marks.Sum();
Async Keywords
async // marks method as asynchronous
await // suspends until Task completes
// Example
async Task<Student> GetStudentAsync(int id)
{
await Task.Delay(100);
return new Student { Id = id, Name = "Sahasra" };
}
Query (LINQ) Keywords
// Used in query syntax
from // data source
where // filter
select // projection
group // grouping
into // continuation
orderby // sorting
join // join collections
let // intermediate variable
on / equals / by // join clauses
// Example
var result =
from s in students
where s.Percentage >= 75
orderby s.Percentage descending
select new { s.Name, s.Percentage };
Contextual Keywords (Not Reserved - Special in Context)
// These are NOT reserved - can use as identifiers but have special meaning in context
var // type inference
dynamic // dynamic type
yield // iterator (yield return, yield break)
value // in property setter
get / set / init // property accessors
add / remove // event accessors
where // generic constraints
when // catch filter + pattern matching
record // immutable type (C# 9+)
required // required property (C# 11+)
file // file-scoped access modifier (C# 11+)
scoped // lifetime scope for ref structs
Escape Reserved Keywords with @
Complete Keyword Count by Category
| Category | Keywords |
|---|---|
| Types | 16 |
| Declaration | 8 |
| Access Modifiers | 6 |
| Modifiers | 12 |
| Control Flow | 11 |
| Exception | 4 |
| Object | 10 |
| Type Checking | 2 |
| Overflow | 2 |
| Parameter Modifiers | 4 |
| Async | 2 |
| LINQ Query | 14 |
| Total | ~79 |
Common Mistakes
? Trying to use keyword as variable name:
int class = 10; // ERROR - class is reserved
string @event = ""; // OK - but bad style
? Use clear names instead of escaping:
int studentClass = 10; // Clear intent
string eventName = ""; // Better than @event
? Confusing abstract, virtual, override:
public class Student
{
public virtual string GetGrade() => "A"; // Can be overridden
public abstract void Calculate(); // Error - method has body
}
? Correct usage:
public abstract class Person
{
public virtual string GetGrade() => "A"; // Can override, has implementation
public abstract string GetName(); // Must override, no implementation
}
public class Student : Person
{
public override string GetName() => "Sahasra";
public override string GetGrade() => "A+";
}
? Using const for values that change:
public const decimal LateFeeRate = 0.01m; // Can't change at runtime!
// Later in code:
LateFeeRate = 0.02m; // Error - const is immutable
? Use readonly for runtime values:
public static readonly decimal LateFeeRate = 0.01m; // Can be set once
// In static constructor:
static Config()
{
LateFeeRate = decimal.Parse(configFile); // OK
}
? Forgetting @ when legacy DB column matches keyword:
public class Student
{
public string class { get; set; } // Error - class is keyword
}
? Use @ to escape:
public class Student
{
[Column("class")]
public string @class { get; set; } // OK, maps to "class" column
}
? Not understanding sealed (can't inherit):
public sealed class Final { }
public class Derived : Final { } // Error - sealed class can't be inherited
? Sealed prevents inheritance:
public class Derived : Student { } // OK - Student not sealed
// Override in sealed prevents further override
public sealed override string GetGrade() => "A+"; // No subclass can override
Best Practices
- Know the keywords in your domain - Understand types, modifiers you use most
- Prefer not escaping keywords - Use clear names instead of
@keyword - Use
abstractfor interfaces needing code - Default to interfaces, use abstract only if shared code needed - Mark virtual only if subclass override expected - Don't mark methods virtual by default
- Use
readonlyover const for runtime values - More flexible - Prefer
ispattern matching overas- More modern, safer - Use
nameof()instead of string literals - Refactor-safe parameter names - Mark classes
sealedif no subclassing needed - Signals intent, allows optimizations - Understand modifier combinations -
protected internal(OR),private protected(AND) - Use
paramsfor optional argument lists - More readable than arrays - Document why
checked/uncheckedneeded - Overflow is rare, document when it matters - Know contextual vs reserved -
varnot reserved, can use as name (but don't)
abstract: Method has NO implementation. Derived class MUST override. Used in abstract classes/interfaces.
virtual: Method HAS implementation. Derived class CAN override. Optional.
override: Used in derived class to override virtual/abstract.
public abstract class Person
{
public abstract string GetName(); // No body, must override
public virtual string GetEmail() => ""; // Has default, can override
}
public class Student : Person
{
public override string GetName() => "Sahasra"; // Must override
public override string GetEmail() => "Sahasra@x.com"; // Optional override
}
Abstract = mandatory, virtual = optional.
const: Compile-time constant. Value baked into code. Can't change ever.
readonly: Runtime constant. Set once (constructor or initializer). More flexible.
public const double PI = 3.14159; // Compile-time, never changes
public readonly int StudentId; // Set in constructor, then fixed
public Student(int id)
{
StudentId = id; // Set once here
}
PI = 3.1; // Error
StudentId = 100; // Error
Use const for mathematical constants. Use readonly for values computed/configured at runtime.
sealed class: Can't be inherited. End of inheritance chain.
sealed override: Subclass can't further override this method.
public sealed class Final { }
public class Derived : Final { } // ERROR - sealed
public class Base
{
public virtual void Work() { }
}
public class Derived : Base
{
public sealed override void Work() { } // Can override once
}
public class Further : Derived
{
public override void Work() { } // ERROR - sealed
}
Sealed prevents inheritance, signals "don't subclass", allows JIT optimizations.
Abstract class: IS-A relationship. Can have code, state, constructors. Single inheritance.
Interface: CAN-DO capability. No code (pre-C# 8), no state. Multiple implementation.
public abstract class Animal // IS-A - an animal
{
public void Breathe() { } // Shared code
public int Age { get; set; } // State
public abstract void Move();
}
public interface ISwimmable // CAN-DO - can swim
{
void Swim(); // No implementation (pre-C# 8)
}
public class Fish : Animal, ISwimmable // One abstract, multiple interfaces
{
public override void Move() => Swim();
public void Swim() { }
}
Abstract when shared code. Interface when just contract.
Contextual keywords NOT reserved - can use as identifiers. But have special meaning in context.
var x = 10; // var - type inference, contextual
int yield = 5; // yield as variable OK, but yield return in iterator has special meaning
// These work:
string var = "text"; // Legal but confusing
string value = "x"; // OK - value contextual in property setter
// But in iterator - yield has special meaning:
IEnumerable<int> Count()
{
for (int i = 1; i <= 10; i++)
yield return i; // yield return - special, not regular return
}
Contextual keywords flexible but use carefully to avoid confusion.
Only when legacy code forces you. Don't do it otherwise.
// ? Bad - unnecessary escape
string @this = "value";
// ? Good - legacy DB column named "class"
[Column("class")]
public string @class { get; set; }
// ? Good - API contract requires "namespace"
public class ApiResponse
{
[JsonPropertyName("namespace")]
public string @namespace { get; set; }
}
Use @ only when external constraint (DB column, API field, legacy code) forces keyword usage. Otherwise rename.
Use ChatGPT, Claude, or Copilot to go deeper on C# reserved keywords. Try these prompts:
"What is the difference between abstract, virtual, and override keywords in C#?""Explain the difference between const and readonly in C# with examples""What does the sealed keyword do in C# and when should I use it?""Quiz me on C# keywords - describe a keyword and I will name it"
💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.