When building modern .NET apps, understanding C# class and method keywords is essential for writing clean, maintainable, and scalable code. From inheritance to visibility and immutability, these keywords shape how your classes interact and behave.
In this guide, we’ll cover:
✅ base
, virtual
, override
, new
, static
, partial
✅ Plus more powerful keywords: abstract
, sealed
, readonly
, const
, interface
, internal
, protected
, private
, public
✅ Real-world examples, best practices, and caveats!
base
— Accessing Base Class Members
The base
keyword is used to:
Access base class methods, properties, or constructors from a derived class.
Real-Time Example: Logging with a Base Service
public class Logger
{
public virtual void Log(string message)
{
Console.WriteLine($"[Base] {message}");
}
}
public class FileLogger : Logger
{
public override void Log(string message)
{
base.Log(message); // Calls the base implementation
Console.WriteLine($"[FileLogger] {message}");
}
}
Explanation:base.Log(message)
allows FileLogger
to call the base class implementation before adding additional logic.
virtual
— Enabling Polymorphism
The virtual
keyword allows a method or property to be overridden in a derived class.
Example:
public class Animal
{
public virtual void Speak()
{
Console.WriteLine("Animal speaks.");
}
}
override
— Customizing Base Behavior
The override
keyword modifies or extends a virtual
or abstract
member from a base class.
Example:
public class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("Dog barks.");
}
}
Explanation:Dog
provides its own implementation of Speak()
while preserving polymorphic behavior.
new
— Hiding Members
The new
keyword hides a member from the base class rather than overriding it.
Example:
public class Cat : Animal
{
public new void Speak()
{
Console.WriteLine("Cat meows.");
}
}
Explanation:Cat.Speak()
hides the base implementation instead of overriding it. This means if you reference the object as Animal
, you’ll get the base version.
Animal myCat = new Cat();
myCat.Speak(); // Outputs: "Animal speaks."
static
— Shared Members
The static
keyword defines members that belong to the class itself, not to any instance.
Example:
public static class MathHelper
{
public static int Square(int x) => x * x;
}
Usage:
int result = MathHelper.Square(5);
Console.WriteLine(result); // Outputs: 25
partial
— Splitting Code Across Files
The partial
keyword allows a class, struct, or interface to be split across multiple files.
Example:
File1.cs
public partial class OrderProcessor
{
public void ProcessOrder()
{
Console.WriteLine("Processing order...");
}
}
File2.cs
public partial class OrderProcessor
{
public void ValidateOrder()
{
Console.WriteLine("Validating order...");
}
}
Usage:
var processor = new OrderProcessor();
processor.ValidateOrder();
processor.ProcessOrder();
Explanation:
Great for splitting large classes (e.g., auto-generated code plus manual logic).
abstract
— For Incomplete Classes and Methods
Description:
An abstract
class cannot be instantiated directly. It can contain both implemented and abstract (unimplemented) methods.
https://medium.com/@dotnetfullstackdev
public abstract class Shape
{
public abstract double CalculateArea();
}
Explanation:
Forces derived classes to provide their own implementation of
CalculateArea()
.Great for defining base contracts with shared behavior.
sealed
— Preventing Inheritance
Description:
The sealed
keyword prevents a class from being inherited.
Example:
public sealed class FinalLogger
{
public void Log(string message) => Console.WriteLine(message);
}
Explanation:
Ensures no subclass can change its behavior.
Often used for performance or security reasons.
readonly
— Immutable Fields
Description:
A readonly
field can only be assigned in the constructor (or at declaration).
Example:
public class Config
{
public readonly string AppName = "MyApp";
public readonly string Environment;
public Config(string environment)
{
Environment = environment;
}
}
Explanation:
Provides immutability while allowing values to be assigned at construction.
const
— Compile-Time Constants
Description:
A const
field is a compile-time constant—it must be assigned at declaration.
Example:
public class MathConstants
{
public const double Pi = 3.14159;
}
Explanation:
Value cannot change at runtime.
Substituted at compile time (faster but less flexible than
readonly
).
Real-World Code
Imagine building a payments system with different payment processors:
// PaymentProcessor.cs
public abstract class PaymentProcessor
{
public readonly string ProcessorName;
protected PaymentProcessor(string name)
{
ProcessorName = name;
}
public abstract void Process(decimal amount);
}
// PayPalProcessor.cs
public class PayPalProcessor : PaymentProcessor
{
public PayPalProcessor() : base("PayPal") {}
public override void Process(decimal amount)
{
Console.WriteLine($"{ProcessorName} processed payment: {amount:C}");
}
}
// PaymentUtilities.cs
public static class PaymentUtilities
{
public const decimal TaxRate = 0.07m;
public static decimal CalculateTotal(decimal amount)
{
return amount + (amount * TaxRate);
}
}
// Program.cs
internal class Program
{
private static void Main()
{
PaymentProcessor processor = new PayPalProcessor();
decimal total = PaymentUtilities.CalculateTotal(100m);
processor.Process(total);
}
}
Conclusion
These C# keywords are more than syntax — they’re the building blocks of robust, maintainable, and powerful applications. Mastering them helps you write clean, effective code that leverages inheritance, polymorphism, and modularity to build complex systems with ease.