Hoppa till innehåll

Klasser, objekt och konstruktorer

↑

Exemplen är oberoende C#-utdrag för moderna .NET-konsolprojekt, om inget annat anges. Klassdeklarationer och toppnivåkod kan placeras i samma Program.cs-fil, med toppnivåkoden först.

En klass beskriver en referenstyp och ett objekt är en instans av klassen. Fält lagrar tillstånd, metoder beskriver beteende och konstruktorer skapar giltigt starttillstånd.

new skapar en instans. Varje instans har egna icke-statiska fält. En konstruktor heter som klassen, har ingen returtyp och körs när instansen skapas.

Example.cs
Player player = new("Alex");
player.AddPoints(5);
Console.WriteLine($"{player.Name}: {player.Score}");
public class Player
{
public string Name { get; }
public int Score { get; private set; }
public Player(string name) => Name = name;
public void AddPoints(int amount) => Score += amount;
}

Använd privata fält och metoder som håller objektets tillstånd giltigt. Publika egenskaper kan visa data utan att tillåta fri ändring. En konstruktor bör kontrollera argument som krävs för ett giltigt objekt.

Example.cs
public sealed class BankAccount
{
public decimal Balance { get; private set; }
public void Deposit(decimal amount)
{
if (amount <= 0) throw new ArgumentOutOfRangeException(nameof(amount));
Balance += amount;
}
}

Oftast placeras en huvudtyp per fil, men det är en konvention och inget C#-krav. partial låter en typ delas över flera filer, ofta för genererad kod. Delarna kompileras till samma typ i samma assembly.

Example.cs
// Player.Core.cs
public partial class PlayerProfile { public string Name = "Alex"; }
// Player.Stats.cs (another file, same namespace and assembly)
public partial class PlayerProfile { public int Level = 1; }

Fördjupning: skilj mellan ritning och objekt

Section titled “Fördjupning: skilj mellan ritning och objekt”

En klass beskriver en typ: vilken data dess instanser har och vilka operationer de erbjuder. new Player("Alex") skapar ett objekt och anropar en instanskonstruktor som bestämmer starttillståndet. Två anrop till new skapar normalt två självständiga objekt även om argumenten är identiska. En variabel med klasstyp innehåller vanligen en referens till ett objekt, inte en inbäddad kopia av alla dess fält.

Program.cs
var first = new Player("Alex");
Player alias = first;
var second = new Player("Alex");
alias.Level = 5;
Console.WriteLine(first.Level); // 5: samma objekt
Console.WriteLine(second.Level); // 1: annat objekt
public sealed class Player
{
public string Name { get; }
public int Level { get; set; } = 1;
public Player(string name) => Name = name;
}

Detta är viktigt när objekt skickas till metoder. Metoden får en kopia av referensen och kan därför ändra samma objekt. Att tilldela om metodens lokala parameter byter däremot inte automatiskt vilket objekt anroparens variabel pekar på.

En konstruktor ska skapa ett giltigt och användbart starttillstånd: ta emot nödvändiga parametrar, validera dem, fylla i skrivskyddade medlemmar och undvika halvfärdiga objekt. Konstruktorer kan överlagras; : this(...) återanvänder en annan konstruktor och : base(...) anropar en basklasskonstruktor. Undvik tung fil- eller nätverks-I/O vid vanlig objektkonstruktion eftersom skapandet då blir långsamt och svårt att testa.

Fält, egenskaper och metoder har olika ansvar

Section titled “Fält, egenskaper och metoder har olika ansvar”

Använd fält för intern lagring, egenskaper för kontrollerade värden och metoder för handlingar. En klass bör ha ett tydligt ansvar i stället för att samtidigt hantera indata, sparfiler, UI och stridslogik. Samma tanke gäller Unity-komponenter, men en MonoBehaviour läggs normalt till på ett GameObject i stället för att skapas med new.

En publik klass per tydligt namngiven .cs-fil är en användbar konvention, inte ett absolut krav i C#. Flera klasser kan ligga i samma fil och partial låter en typ delas mellan filer, vilket används av bland annat kodgeneratorer. Namespaces grupperar namn, assemblies avgör kompileringsgränser och mappar är en projektkonvention snarare än en åtkomstregel.

Ge varje klass ett tydligt ansvar och initiera nödvändiga värden i konstruktorn.

Blanda inte ihop en klass och filen .cs där den ligger. Publika ändringsbara fält kan ändras av annan kod utan kontroll.

Skapa klassen Book vars konstruktor tar emot en titel och visar den skrivskyddat.

Visa ett lösningsförslag

public class Book { public string Title { get; } public Book(string title) => Title = title; }.