Konstruktorer
Constructors är som digitala arkitekter som bygger dina objekt från grunden! De bestämmer vad som händer när du säger new MyClass() - ingen mer slumpmässigt initialiserade objekt! 🏠⚡
🎯 TL;DR
Constructors = objekt-byggare. Static properties = klass-level data. Const vs readonly = kompilerings-konstanter vs runtime-konstanter. Records = automatiska value-objects. Enums = namngivna konstanter. Allt för att bygga robusta, välorganiserade klasser!
🎯 Efter denna artikel kommer du att:
- Behärska alla constructor-typer - default, parameterized, copy, static 🔨
- Förstå static properties vs instance properties - klass-data vs objekt-data 📊
- Veta skillnaden mellan const och readonly - kompilering vs runtime 🔒
- Använda enums professionellt - namngivna konstanter som rocks 🏷️
- Skapa moderna records - automatic value objects med C-Sharp 14 syntax 📦
- Designa robusta klass-hierarkier - från grund till avancerat 🏛️
🏗️ Alla Constructor-Typer - Komplett Guide
🎯 Decision Matrix - Vilken Constructor ska jag använda?
| Scenario | Constructor Type | När använd |
|---|---|---|
| Enkel init | Default (parameterlös) | Objekt kan vara giltigt utan extra data |
| Kräv data | Parameterized | Du måste validera eller kräva specifik data |
| Flexibilitet | Överlagrade | Flera init-vägar (basic vs advanced setup) |
| Modern stil | Primary Constructor (C-Sharp 12+) | Minimal boilerplate, record-lik smidighet |
| Singleton | Private Constructor | Kontrollera objektskapande |
| Kopiera objekt | Copy Constructor | Duplicera befintligt objekt |
| Klass-init | Static Constructor | Initiera statiska resurser en gång |
⚡ 2. Parameterized Constructor - Kräv Data
public class Player
{
public string Name { get; }
public int Level { get; private set; }
public DateTime JoinDate { get; }
// Parameterized constructor med validation
public Player(string name, int level)
{
// Validera parametrar FÖRST
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("❌ Player name cannot be empty!");
if (level < 1 || level > 100)
throw new ArgumentOutOfRangeException(nameof(level), "❌ Level must be 1-100");
Name = name;
Level = level;
JoinDate = DateTime.Now;
Console.WriteLine($"✅ Player {Name} created at level {Level}!");
}
}
// Usage - MÅSTE ge parametrar
var player = new Player("Marcus", 42);
🚀 4. Primary Constructor (C-Sharp 12+) - Modern Magic
// Primary constructor - parametrar i class declaration!
public class User(string name, string email, int age)
{
public string Name { get; } = name ?? throw new ArgumentNullException(nameof(name));
public string Email { get; } = IsValidEmail(email) ? email : throw new ArgumentException("Invalid email");
public int Age { get; } = age >= 0 ? age : throw new ArgumentException("Age cannot be negative");
public string DisplayName => $"{Name} ({Age} years old)";
// Validation method
private static bool IsValidEmail(string email) =>
!string.IsNullOrEmpty(email) && email.Contains('@');
public override string ToString() => $"{Name} <{Email}>";
}
// Usage - clean och modern!
var user = new User("Marcus", "marcus@example.com", 35);
Console.WriteLine(user.DisplayName);
🏭 6. Singleton Pattern med Private Constructor
public sealed class Logger
{
// Lazy initialization - skapas först när den behövs
private static readonly Lazy<Logger> _instance = new(() => new Logger());
public static Logger Instance => _instance.Value;
// Private constructor - förhindrar multiple instances
private Logger()
{
Console.WriteLine("📝 Logger initialized - this happens only ONCE!");
}
public void Log(string message)
{
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
Console.WriteLine($"[{timestamp}] {message}");
}
}
// Usage - samma instans överallt!
Logger.Instance.Log("Application started");
Logger.Instance.Log("User logged in");
var logger1 = Logger.Instance;
var logger2 = Logger.Instance;
Console.WriteLine($"Same instance? {ReferenceEquals(logger1, logger2)}"); // True!
⚙️ 8. Static Constructor - Klass-Level Init
public class GameConfiguration
{
public static Dictionary<string, int> DefaultStats { get; private set; }
public static string[] AvailableClasses { get; private set; }
public static DateTime ServerStartTime { get; private set; }
// Static constructor - körs EN GÅNG när klassen först används
static GameConfiguration()
{
Console.WriteLine("🔧 Initializing game configuration...");
// Ladda default stats
DefaultStats = new Dictionary<string, int>
{
["Warrior"] = 100,
["Mage"] = 60,
["Archer"] = 80,
["Healer"] = 70
};
// Ladda available classes
AvailableClasses = DefaultStats.Keys.ToArray();
ServerStartTime = DateTime.Now;
Console.WriteLine($"✅ Game config loaded with {DefaultStats.Count} classes");
}
// Regular static method
public static int GetDefaultHealth(string className)
{
return DefaultStats.TryGetValue(className, out var health) ? health : 50;
}
}
// Usage - static constructor körs automatiskt vid första användning
Console.WriteLine($"Warrior health: {GameConfiguration.GetDefaultHealth("Warrior")}");
// Output:
// 🔧 Initializing game configuration...
// ✅ Game config loaded with 4 classes
// Warrior health: 100
😄 Obligatorisk Dad Joke
Varför gillar constructors aldrig överraskningar?
För att de vill alltid veta exakt vad de bygger från början! 🏗️😄
“Hej, jag är Constructor. Jag tar dina parametrar och bygger something awesome!”