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.
Snabböversikt
Section titled “Snabböversikt”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.
Så fungerar det
Section titled “Så fungerar det”Medlemmar och objekt
Section titled “Medlemmar och objekt”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.
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;}Inkapsling och ansvar
Section titled “Inkapsling och ansvar”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.
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; }}Flera filer och partial-klasser
Section titled “Flera filer och partial-klasser”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.
// Player.Core.cspublic 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”Vad händer när new körs?
Section titled “Vad händer när new körs?”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.
var first = new Player("Alex");Player alias = first;var second = new Player("Alex");
alias.Level = 5;Console.WriteLine(first.Level); // 5: samma objektConsole.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å.
Konstruktorns ansvar
Section titled “Konstruktorns ansvar”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.
Organisera ett riktigt projekt
Section titled “Organisera ett riktigt projekt”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.
När och varför?
Section titled “När och varför?”Ge varje klass ett tydligt ansvar och initiera nödvändiga värden i konstruktorn.
Vanligt misstag
Section titled “Vanligt misstag”Blanda inte ihop en klass och filen .cs där den ligger. Publika ändringsbara fält kan ändras av annan kod utan kontroll.
Testa själv
Section titled “Testa själv”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; }.
