Classes & Objects
A class is a reference-type blueprint — fields, properties, methods, events. With record, struct, and interface all in the language, the choice of class is now a deliberate one: identity-based, mutable, reference semantics.
Properties, ctors, sealed, partial
EXAMPLE
// 1) Modern C# class with a primary constructor (C# 12+)
public class User(string name, string email)
{
public string Name { get; set; } = name;
public string Email { get; init; } = email; // init-only — set during construction
public DateTime CreatedAt { get; } = DateTime.UtcNow;
public bool Verified { get; private set; } // private setter
public void Verify() => Verified = true;
public override string ToString() => $"{Name} <{Email}>";
}
var u = new User("Ada", "ada@example.com");
u.Verify();
Console.WriteLine(u);
// 2) Required members — caller MUST set them
public class Order
{
public required string Sku { get; init; }
public required int Qty { get; init; }
public decimal Price { get; init; }
}
var o = new Order { Sku = "A-100", Qty = 2, Price = 9.99m };
// 3) Inheritance + sealed
public class Animal { public virtual string Sound() => "?"; }
public sealed class Cat : Animal { public override string Sound() => "meow"; }
// sealed = cannot be inherited; the JIT can devirtualise calls
// 4) Abstract base + concrete implementations
public abstract class Shape
{
public abstract double Area { get; }
public sealed override string ToString() => $"{GetType().Name} area={Area:F2}";
}
public class Rect(double w, double h) : Shape
{
public override double Area => w * h;
}
public class Circle(double r) : Shape
{
public override double Area => Math.PI * r * r;
}
// 5) Partial class — split across files, common in source-generators
public partial class GeneratedDto
{
public string Id { get; init; } = string.Empty;
}
// other file:
public partial class GeneratedDto
{
public string DisplayName => $"#{Id}";
}
// 6) Static class — utility methods, no instances
public static class StringEx
{
public static string Truncate(this string s, int max) =>
s.Length <= max ? s : s[..max] + "…";
}
"Hello world".Truncate(8); // → "Hello wo…"
// 7) When to pick class vs record vs struct
// class → reference semantics, identity, mutable state
// record → value-equality semantics, perfect for DTOs
// struct → small (< 16 bytes), value semantics, copied
Why it matters
Modern C# pushes you toward records for data and classes for behaviour with identity. Use required + init to make construction explicit and safe — the compiler enforces what your invariants demand.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
public class User {
public string Name { get; set; }
public int Age { get; set; }
public User(string name, int age) { Name = name; Age = age; }
public string Greet() => \$"hi, {Name}";
}
Try it Yourself »
Exercise
Instantiate a class.
var u =
User("Ada", 36);
Three letters.
Discussion
Loading…