Egenskaper

Properties är som smarta dörrvakter för dina klassvariabler! De kontrollerar vem som får komma in, vad de får göra, och håller ordning på allt. Ingen mer anarchy med publika fields! 🚪✋

🎯 Efter denna artikel kommer du att:

  • Förstå properties vs fields - skillnaden mellan rå data och kontrollerad access 🔒
  • Skapa properties i alla stilar - från gammal stil till modern C-Sharp 14 ✨
  • Använda init-only properties - sätt en gång, använd för evigt! 🔧
  • Hantera computed properties - värden som beräknas on-the-fly 🧮

📊 Evolution of Properties - Från Stenåldern till C-Sharp 14

🏺 Stenåldern: Public Fields (Gör ALDRIG detta)


// ❌ GAMMAL & FARLIG - ingen kontroll!
public class BadBankAccount
{
    public decimal balance;  // Vem som helst kan sätta vad som helst!
}

// Somewhere else in code:
var account = new BadBankAccount();
account.balance = -1000000;  // 💸 BANKRUPTCY! Ingen kan stoppa oss!

🏛️ Klassisk Epok: Full Properties (C-Sharp 1.0)


// ✅ KLASSISK - full kontroll men verbose
public class ClassicBankAccount
{
    private decimal _balance;  // Private field - the real data

    // Full property with validation
    public decimal Balance
    {
        get
        {
            Console.WriteLine($"🔍 Balance requested: {_balance}");
            return _balance;
        }
        set
        {
            if (value < 0)
                throw new ArgumentException("❌ Saldot kan inte vara negativt!");

            Console.WriteLine($"💰 Setting balance from {_balance} to {value}");
            _balance = value;
        }
    }
}

🏢 Modern Epok: Auto-Properties (C-Sharp 3.0)


// ✅ MODERN - kortare men fortfarande kraftfull
public class ModernBankAccount
{
    // Auto-property - compiler skapar private field automatically
    public decimal Balance { get; set; }

    // Auto-property med validation
    private decimal _balance;
    public decimal ValidatedBalance
    {
        get => _balance;
        set => _balance = value >= 0 ? value : throw new ArgumentException("❌ Negativt saldo!");
    }

    // Read-only auto property
    public string AccountNumber { get; private set; }

    // Get-only computed property
    public string DisplayBalance => $"{Balance:C} SEK";
}

🚀 Futuristisk Era: Init-Only Properties (C-Sharp 9+)


// ✅ C-Sharp 14 STYLE - immutable by default!
public class FuturisticBankAccount
{
    // Init-only - can only be set during construction
    public string AccountNumber { get; init; } = string.Empty;
    public string Owner { get; init; } = string.Empty;
    public DateTime CreatedDate { get; init; } = DateTime.Now;

    // Regular property for things that change
    public decimal Balance { get; set; }

    // Required property - must be set during construction
    public required string Bank { get; init; }

    // Computed property with expression body
    public string AccountInfo => $"🏦 {Bank}: {AccountNumber} ({Owner})";

    // Complex computed property
    public string BalanceStatus => Balance switch
    {
        < 0 => "🔴 Skuld",
        < 1000 => "🟡 Lågt saldo",
        < 10000 => "🟢 Normalt saldo",
        _ => "💎 Rik person!"
    };
}

🔒 Property Access Levels - Vem Får Göra Vad?


public class SecurityExample
{
    // Public get/set - alla kan läsa och skriva
    public string PublicData { get; set; } = "Everyone can access";

    // Public get, private set - alla kan läsa, bara denna class kan skriva
    public string ReadOnlyForOthers { get; private set; } = "Read-only outside";

    // Public get, protected set - alla kan läsa, bara denna class + barn kan skriva
    public string ReadOnlyForPublic { get; protected set; } = "Family can write";

    // Public get, init set - alla kan läsa, bara constructor kan skriva
    public string SetOnceOnly { get; init; } = "Set during construction only";

    // Private property - bara denna class
    private string SecretData { get; set; } = "Top secret";

    // Protected property - bara denna class + barn
    protected string FamilySecret { get; set; } = "Family only";

    public void DemonstrateAccess()
    {
        // Denna class kan göra allt
        PublicData = "Changed by owner";
        ReadOnlyForOthers = "Owner can change";
        ReadOnlyForPublic = "Owner can change";
        SecretData = "Owner knows all secrets";
        FamilySecret = "Owner shares with family";

        // SetOnceOnly kan INTE ändras här - bara i constructor/init!
        // SetOnceOnly = "Nope!";  // ❌ Compilation error
    }
}

public class SecurityChild : SecurityExample
{
    public void ChildAccess()
    {
        // Child class kan accessa protected
        FamilySecret = "Child changed family secret";
        ReadOnlyForPublic = "Child can write this";

        // Men inte private
        // SecretData = "Nope!";  // ❌ Not accessible
    }
}

🎯 Property Patterns - When to Use What

📋 Decision Matrix

ScenarioProperty TypeExample
Simple data storageAuto-propertypublic string Name { get; set; }
Read-only dataInit-onlypublic string Id { get; init; }
Computed valueExpression bodypublic string FullName => $"{First} {Last}"
Validated inputFull propertyCustom getter/setter with validation
Expensive calculationLazy/cachedCache result, recalculate when needed
Must be setRequiredpublic required string Name { get; init; }

✅ Property Best Practices


public class BestPracticeExample
{
    // ✅ Use init for immutable data
    public required string Id { get; init; }

    // ✅ Use auto-properties for simple data
    public string Name { get; set; } = string.Empty;

    // ✅ Use expression bodies for computed properties
    public string DisplayName => string.IsNullOrEmpty(Name) ? "Unknown" : Name;

    // ✅ Use validation in setters when needed
    private int _age;
    public int Age
    {
        get => _age;
        set => _age = value >= 0 ? value : throw new ArgumentException("Age cannot be negative");
    }

    // ✅ Use private setters for controlled access
    public DateTime CreatedAt { get; private set; } = DateTime.Now;

    // ✅ Use collections with private setters
    public List<string> Tags { get; private set; } = [];

    public void AddTag(string tag)
    {
        if (!string.IsNullOrEmpty(tag))
            Tags.Add(tag);
    }
}

💡 Marcus Property Wisdom

“Properties är som att hyra ut lägenhet - du vill ha kontroll över vem som kommer in, vad de gör där, och att de städar efter sig! Ingen vill ha en lägenhet där vem som helst kan komma och gå som de vill!” 🏠🔑

Real story: 2019 debuggade jag en bug i 3 dagar som visade sig vara att någon satte ett negativt värde direkt på en public field. Efter det: INGA fler public fields, bara properties med validation! 😅

Pro tip: Börja alltid med auto-properties. Uppgradera till full properties bara när du behöver validation eller custom logic. YAGNI (You Ain’t Gonna Need It) gäller här också! 🚀

Ready för Constructors och Records? Properties är grunden - nu bygger vi objekt som proffs! 🏗️


Upp

Upp


Licens: Apache 2.0 | © 2023 Marcus Medina, Campus Mölndal. Alla rättigheter förbehållna.
Du får använda och modifiera detta verk enligt villkoren i Apache License, Version 2.0. Du får inte använda detta verk för kommersiella ändamål utan tillstånd från upphovsmannen.