ref — referensparametrar

ref skickar en referens till originalet istället för en kopia. Det metoden gör med parametern påverkar direkt den variabel du skickade in.

Nytt på värde- vs referenstyper? Läs Värde- och referenstyper först — den förklarar varför ref ens behövs för ett int men aldrig för en List<T>.

När du läst detta ska du kunna

  • Förklara skillnaden mellan värdeöverföring och ref
  • Använda ref för att låta en metod ändra ett värde hos anroparen
  • Förklara skillnaden mellan ref och out

Utan ref — originalet påverkas inte

void TryDouble(int number)
{
number *= 2;
}
int value = 10;
TryDouble(value);
Console.WriteLine(value); // 10 — oförändrat

Med ref — originalet ändras

void Double(ref int number)
{
number *= 2;
}
int value = 10;
Double(ref value); // ref krävs vid anrop också
Console.WriteLine(value); // 20

Output

20

ref måste stå vid både definitionen och anropet.

Praktiskt exempel — swap

Klassiskt exempel: byt plats på två variabler utan att returnera något.

void Swap(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
}
int x = 3, y = 7;
Swap(ref x, ref y);
Console.WriteLine($"x={x}, y={y}");

Output

x=7, y=3

ref vs out

refout
Måste vara initialiserad innan anropJaNej
Metoden måste tilldela värdetNejJa
Används förLäsa och ändraReturnera extra värden
Typiskt mönsterSwap, modify-in-placeTryParse
// ref: variabeln måste vara satt FÖRE anropet
int a = 5;
Modify(ref a);
// out: variabeln behöver INTE vara satt före anropet
Compute(out int b);

Undvik ref i vanliga fall

ref kan göra koden svårare att följa — funktioner med sidoeffekter är svårare att testa och resonera kring. Föredra returvärden eller tupler för de flesta fall.

// Hellre så här:
(int a, int b) Swap(int a, int b) => (b, a);
var (x, y) = Swap(3, 7);

Ännu hellre — swap utan metod alls

Du behöver inte ens en metod. Tuple-deconstruction (se Tupler) kan byta plats på två variabler i en enda rad:

int x = 3, y = 7;
(x, y) = (y, x);
Console.WriteLine($"x={x}, y={y}");

Output

x=7, y=3

(y, x) bygger en ny tuple med de gamla värdena i omvänd ordning, och (x, y) = packar upp den rakt in i x och y igen — allt sker samtidigt, så ingen temp-variabel behövs och ingen ref heller.

Regler

  • ref-variabeln måste vara initialiserad innan anropet
  • ref krävs vid både definition och anrop
  • Fungerar med value types (int, struct) — ger faktisk referenssemantik

TL;DR

ref = skicka originalvariabeln. Metoden kan läsa och ändra den. Använd sparsamt — föredra returvärden.