Back to Blog
C#

C# Class Declaration: Syntax and Variations

c# class declaration: Learn the syntax and variations of C# class declarations, including access modifiers, inheritance, static classes, partial classes, and nested ty...

C#class declarationobject-oriented programmingaccess modifiersinheritancepartial classes
Illustration of a C# class declaration showing the class keyword, a class name, and braces, with subtle icons for access modifiers and inheritance.

A C# class declaration defines the blueprint for an object type. The syntax is simple, but the variations—access modifiers, inheritance, static and partial classes—determine how the type is visible, instantiated, and organized. This article walks through the core declaration forms and the rules that govern them.

Basic Class Declaration Syntax

The most basic class declaration uses the class keyword followed by a name and a body enclosed in braces:

public class Customer { // members go here }

The public keyword is an access modifier. If omitted, the class is internal by default, meaning it is accessible only within the same assembly. The class name should follow C# naming conventions, typically PascalCase. The body can contain fields, properties, methods, events, constructors, and nested types.

A class declaration can also specify a base class and implemented interfaces. The base class, if any, must appear first after a colon, followed by a comma-separated list of interfaces:

public class PremiumCustomer : Customer, IDisposable { // members }

This declaration states that PremiumCustomer inherits from Customer and implements IDisposable. A class can have only one base class but can implement multiple interfaces.

Access Modifiers on Class Declarations

Access modifiers control where a class can be referenced. The available modifiers for a top-level class are public and internal. A public class is accessible from any assembly that references the containing assembly. An internal class is accessible only within the same assembly.

Nested classes, which are declared inside another class, can also use private, protected, protected internal, and private protected. The accessibility of a nested class is limited by both its own modifier and the accessibility of its containing type.

public class Outer { private class Hidden { } protected class ProtectedNested { } }

Here, Hidden is only accessible within Outer, while ProtectedNested is accessible within Outer and any derived class of Outer. Choosing the correct modifier is important for encapsulation and API design.

Declaring Class Members

A class declaration is incomplete without members. The most common members are fields, properties, methods, and constructors. Fields store data, properties expose data with controlled access, methods define behavior, and constructors initialize instances.

public class Order { private int _id; public int Id { get; set; } public decimal Total { get; private set; } public Order(int id) { _id = id; } public void ApplyDiscount(decimal percent) { Total -= Total * percent; } }

Fields and properties can have their own access modifiers, independent of the class. A property with a private setter allows external reads but restricts writes to within the class. Constructors are declared with the same name as the class and no return type. If no constructor is declared, the compiler provides a parameterless one.

Inheritance and Base Class Declarations

Inheritance is declared by specifying a base class after the colon. The derived class inherits all non-private members of the base class, except constructors and finalizers. The base class constructor is called implicitly before the derived class constructor body runs, unless a different base constructor is explicitly invoked.

public class Animal { public string Name { get; set; } public Animal(string name) { Name = name; } } public class Dog : Animal { public Dog(string name) : base(name) { } }

The : base(name) syntax passes the name argument to the base class constructor. If the base class has only a parameterized constructor, the derived class must call it explicitly. Omitting this call causes a compile-time error.

A class can be declared abstract to prevent instantiation, or sealed to prevent further inheritance. These modifiers are placed before the class keyword:

public abstract class Shape { } public sealed class Circle : Shape { }

An abstract class may contain abstract members that derived classes must implement. A sealed class cannot be used as a base class.

Static Classes and Their Declaration Rules

A static class is declared with the static keyword. It cannot be instantiated, and all members must be static. Static classes are typically used for utility functions that do not depend on instance state.

public static class MathHelper { public static int Square(int x) => x * x; } ```n Static classes are implicitly `sealed` and cannot inherit from any class other than `object`. They cannot declare instance constructors, but they can have a static constructor to initialize static state. Attempting to add an instance member to a static class results in a compile-time error. Because a static class cannot be instantiated, it cannot be used as a type argument for a generic constraint that requires a constructor. This limitation is important when designing generic APIs. ## Partial Class Declarations A partial class declaration splits the definition across multiple files or regions. Each part must use the `partial` keyword, and all parts must have the same accessibility and base class. The compiler merges them into a single type at compile time. ```csharp // File: Customer.cs public partial class Customer { public string Name { get; set; } } // File: Customer.Validation.cs public partial class Customer { public bool Validate() => !string.IsNullOrEmpty(Name); }

Partial classes are useful when generated code and hand-written code need to coexist, such as in designer files or code generators. They also help organize large classes by separating concerns into files. However, overusing partial classes can make the type harder to navigate, so they should be applied only when the split provides a clear benefit.

Nested Class Declarations

A nested class is declared inside another class. It has access to private members of the containing type, even if those members are private. Nested classes are often used for helper types that are only relevant to the outer class.

public class Tree { private class Node { public int Value; public Node Left; public Node Right; } private Node _root; }

Nested classes can be declared with any access modifier, but private is common when the nested type is an implementation detail. The nesting adds a layer of encapsulation, but it also increases the containing class's responsibility. Consider whether a separate top-level class would be clearer before nesting.

Common Declaration Mistakes and How to Avoid Them

One frequent mistake is forgetting the access modifier on a class that needs to be used from another assembly. The default internal accessibility causes confusing compile-time errors in consuming code. Always specify the intended accessibility explicitly.

Another mistake is declaring a class without a base class when inheritance is expected, or attempting to inherit from a sealed class. The compiler rejects such code, but the error message may not immediately point to the declaration.

When using partial classes, forgetting the partial keyword on one part results in two separate types with the same name, causing a conflict. Ensure every part carries the partial modifier.

Finally, mixing up the order of base class and interface names in the declaration is a common syntactic error. The base class must come first, followed by interfaces. The compiler will report a syntax error if the order is reversed.

Class declaration is the foundation of object-oriented code in C#. Understanding the syntax and its variations prevents many compile-time errors and leads to cleaner type design. Pay attention to accessibility, inheritance, and the special forms like static and partial classes to use them effectively.

c# class declaration: Practical Usage and Code Examples | RYUSLOG DEV