Oktatóanyag: Memóriafoglalások ref
csökkentése biztonsággal
A .NET-alkalmazások teljesítményhangolása gyakran két technikát is magában foglal. Először csökkentse a halomfoglalások számát és méretét. Másodszor csökkentse az adatok másolásának gyakoriságát. A Visual Studio nagyszerű eszközöket biztosít, amelyekkel elemezheti, hogyan használja az alkalmazás a memóriát. Miután megállapította, hogy az alkalmazás hol végez szükségtelen foglalásokat, módosításokat hajt végre a foglalások minimalizálása érdekében. Típusokat típusokká struct
alakíthat átclass
. Biztonsági funkciókkal ref
megőrizheti a szemantikát, és minimalizálhatja a felesleges másolást.
Használja a Visual Studio 17.5-öt az oktatóanyag legjobb élményéhez. A memóriahasználat elemzéséhez használt .NET-objektumfoglalási eszköz a Visual Studio része. A Visual Studio Code és a parancssor használatával futtathatja az alkalmazást, és elvégezheti az összes módosítást. A módosítások elemzési eredményeit azonban nem fogja látni.
A használni kívánt alkalmazás egy IoT-alkalmazás szimulációja, amely több érzékelőt figyel annak megállapítására, hogy egy betolakodó belépett-e egy titkos gyűjteménybe értékekkel. Az IoT-érzékelők folyamatosan küldenek adatokat, amelyek az oxigén (O2) és a szén-dioxid (CO2) levegőben való kombinációját mérik. A hőmérsékletet és a relatív páratartalmat is jelentik. Ezek az értékek mindig kissé ingadoznak. Azonban, amikor egy személy belép a szobába, a változás egy kicsit több, és mindig ugyanabban az irányban: Oxigén csökken, Szén-dioxid növekszik, hőmérséklet nő, mint a relatív páratartalom. Amikor az érzékelők a növekedés megjelenítéséhez egyesülnek, a betolakodó riasztása aktiválódik.
Ebben az oktatóanyagban futtatja az alkalmazást, méri a memóriafoglalásokat, majd a foglalások számának csökkentésével javítja a teljesítményt. A forráskód a mintaböngészőben érhető el.
A kezdőalkalmazás megismerése
Töltse le az alkalmazást, és futtassa a kezdőmintát. Az indítási alkalmazás megfelelően működik, de mivel sok kis objektumot foglal le minden mérési ciklussal, a teljesítménye lassan csökken az idő múlásával.
Press <return> to start simulation
Debounced measurements:
Temp: 67.332
Humidity: 41.077%
Oxygen: 21.097%
CO2 (ppm): 404.906
Average measurements:
Temp: 67.332
Humidity: 41.077%
Oxygen: 21.097%
CO2 (ppm): 404.906
Debounced measurements:
Temp: 67.349
Humidity: 46.605%
Oxygen: 20.998%
CO2 (ppm): 408.707
Average measurements:
Temp: 67.349
Humidity: 46.605%
Oxygen: 20.998%
CO2 (ppm): 408.707
Sok sor el lett távolítva.
Debounced measurements:
Temp: 67.597
Humidity: 46.543%
Oxygen: 19.021%
CO2 (ppm): 429.149
Average measurements:
Temp: 67.568
Humidity: 45.684%
Oxygen: 19.631%
CO2 (ppm): 423.498
Current intruders: 3
Calculated intruder risk: High
Debounced measurements:
Temp: 67.602
Humidity: 46.835%
Oxygen: 19.003%
CO2 (ppm): 429.393
Average measurements:
Temp: 67.568
Humidity: 45.684%
Oxygen: 19.631%
CO2 (ppm): 423.498
Current intruders: 3
Calculated intruder risk: High
Megismerheti a kódot, és megtudhatja, hogyan működik az alkalmazás. A fő program futtatja a szimulációt. A lenyomás <Enter>
után létrehoz egy helyiséget, és összegyűjt néhány kezdeti alapkonfigurációs adatot:
Console.WriteLine("Press <return> to start simulation");
Console.ReadLine();
var room = new Room("gallery");
var r = new Random();
int counter = 0;
room.TakeMeasurements(
m =>
{
Console.WriteLine(room.Debounce);
Console.WriteLine(room.Average);
Console.WriteLine();
counter++;
return counter < 20000;
});
Az alapadatok megállapítása után futtatja a szimulációt a helyiségben, ahol egy véletlenszerű számgenerátor megállapítja, hogy egy betolakodó lépett-e be a szobába:
counter = 0;
room.TakeMeasurements(
m =>
{
Console.WriteLine(room.Debounce);
Console.WriteLine(room.Average);
room.Intruders += (room.Intruders, r.Next(5)) switch
{
( > 0, 0) => -1,
( < 3, 1) => 1,
_ => 0
};
Console.WriteLine($"Current intruders: {room.Intruders}");
Console.WriteLine($"Calculated intruder risk: {room.RiskStatus}");
Console.WriteLine();
counter++;
return counter < 200000;
});
Más típusok tartalmazzák a méréseket, az utolsó 50 mérés átlagát és az összes elvégzett mérés átlagát.
Ezután futtassa az alkalmazást a .NET-objektumfoglalási eszközzel. Győződjön meg arról, hogy a buildet Release
használja, nem a buildet Debug
. A Hibakeresés menüben nyissa meg a Teljesítményprofilozót. Ellenőrizze a .NET-objektumfoglalás nyomon követését , de semmi mást. Futtassa az alkalmazást a befejezéshez. A profilkészítő méri az objektumfoglalásokat és a foglalásokról és a szemétgyűjtési ciklusokról szóló jelentéseket. Az alábbi ábrához hasonló gráfnak kell megjelennie:
Az előző grafikonon látható, hogy a foglalások minimalizálása teljesítménybeli előnyökkel jár. Az élő objektumok gráfjában egy fűrészt ábrázoló minta látható. Ez azt jelzi, hogy számos objektum jön létre, amelyek gyorsan szemétté válnak. Ezeket később gyűjtjük össze, ahogy az objektum deltagráfjában is látható. A lefelé mutató piros sávok szemétgyűjtési ciklust jeleznek.
Ezután tekintse meg a gráfok alatti Foglalások lapot. Ez a táblázat azt mutatja be, hogy milyen típusok vannak a leginkább lefoglalva:
A System.String legtöbb foglalás típusfiókja. A legfontosabb feladat a sztringek lefoglalásának gyakoriságának minimalizálása. Ez az alkalmazás számos formázott kimenetet nyomtat folyamatosan a konzolra. Ebben a szimulációban meg szeretnénk tartani az üzeneteket, ezért a következő két sorra koncentrálunk: a SensorMeasurement
típusra és a IntruderRisk
típusra.
Kattintson duplán a SensorMeasurement
vonalra. Láthatja, hogy az összes foglalás a static
metódusban SensorMeasurement.TakeMeasurement
történik. A metódust a következő kódrészletben tekintheti meg:
public static SensorMeasurement TakeMeasurement(string room, int intruders)
{
return new SensorMeasurement
{
CO2 = (CO2Concentration + intruders * 10) + (20 * generator.NextDouble() - 10.0),
O2 = (O2Concentration - intruders * 0.01) + (0.005 * generator.NextDouble() - 0.0025),
Temperature = (TemperatureSetting + intruders * 0.05) + (0.5 * generator.NextDouble() - 0.25),
Humidity = (HumiditySetting + intruders * 0.005) + (0.20 * generator.NextDouble() - 0.10),
Room = room,
TimeRecorded = DateTime.Now
};
}
Minden mérés egy új SensorMeasurement
objektumot foglal le, amely egy class
típus. Minden SensorMeasurement
létrehozott halomfoglalást okoz.
Osztályok átalakítása szerkezetekre
Az alábbi kód a következő kezdeti deklarációt SensorMeasurement
mutatja:
public class SensorMeasurement
{
private static readonly Random generator = new Random();
public static SensorMeasurement TakeMeasurement(string room, int intruders)
{
return new SensorMeasurement
{
CO2 = (CO2Concentration + intruders * 10) + (20 * generator.NextDouble() - 10.0),
O2 = (O2Concentration - intruders * 0.01) + (0.005 * generator.NextDouble() - 0.0025),
Temperature = (TemperatureSetting + intruders * 0.05) + (0.5 * generator.NextDouble() - 0.25),
Humidity = (HumiditySetting + intruders * 0.005) + (0.20 * generator.NextDouble() - 0.10),
Room = room,
TimeRecorded = DateTime.Now
};
}
private const double CO2Concentration = 409.8; // increases with people.
private const double O2Concentration = 0.2100; // decreases
private const double TemperatureSetting = 67.5; // increases
private const double HumiditySetting = 0.4500; // increases
public required double CO2 { get; init; }
public required double O2 { get; init; }
public required double Temperature { get; init; }
public required double Humidity { get; init; }
public required string Room { get; init; }
public required DateTime TimeRecorded { get; init; }
public override string ToString() => $"""
Room: {Room} at {TimeRecorded}:
Temp: {Temperature:F3}
Humidity: {Humidity:P3}
Oxygen: {O2:P3}
CO2 (ppm): {CO2:F3}
""";
}
A típus eredetileg azért lett létrehozva class
, mert számos double
mérést tartalmaz. Nagyobb, mint amennyit a gyakori elérési utakon szeretne másolni. Ez a döntés azonban sok kiosztást jelentett. Módosítsa a típust a class
típusról a struct
.
Az a-ról class
struct
való váltás néhány fordítóhibát eredményez, mivel az eredeti kód hivatkozási ellenőrzéseket használt null
néhány helyen. Az első az DebounceMeasurement
osztályban van, a AddMeasurement
metódusban:
public void AddMeasurement(SensorMeasurement datum)
{
int index = totalMeasurements % debounceSize;
recentMeasurements[index] = datum;
totalMeasurements++;
double sumCO2 = 0;
double sumO2 = 0;
double sumTemp = 0;
double sumHumidity = 0;
for (int i = 0; i < debounceSize; i++)
{
if (recentMeasurements[i] is not null)
{
sumCO2 += recentMeasurements[i].CO2;
sumO2+= recentMeasurements[i].O2;
sumTemp+= recentMeasurements[i].Temperature;
sumHumidity += recentMeasurements[i].Humidity;
}
}
O2 = sumO2 / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
CO2 = sumCO2 / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
Temperature = sumTemp / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
Humidity = sumHumidity / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
}
A DebounceMeasurement
típus 50 mérésből álló tömböt tartalmaz. Az érzékelő mérései az utolsó 50 mérés átlagaként jelennek meg. Ez csökkenti a zajt az értékekben. A teljes 50 érték leolvasása előtt ezek az értékek a következők null
: . A kód a null
rendszer indításakor a helyes átlag jelentéséhez keres hivatkozásokat. Miután módosította a SensorMeasurement
típust egy szerkezetre, egy másik tesztet kell használnia. A SensorMeasurement
típus tartalmaz egy string
helyiségazonosítót, így ezt a tesztet használhatja:
if (recentMeasurements[i].Room is not null)
A másik három fordítóhiba mind abban a módszerben szerepel, amely ismétlődően végez méréseket egy helyiségben:
public void TakeMeasurements(Func<SensorMeasurement, bool> MeasurementHandler)
{
SensorMeasurement? measure = default;
do {
measure = SensorMeasurement.TakeMeasurement(Name, Intruders);
Average.AddMeasurement(measure);
Debounce.AddMeasurement(measure);
} while (MeasurementHandler(measure));
}
A kezdőmetódusban a helyi változó SensorMeasurement
null értékű hivatkozás:
SensorMeasurement? measure = default;
Most, hogy az SensorMeasurement
struct
class
érték nem egy, a null értékű érték egy null értékű típus. A deklarációt értéktípusra módosíthatja a fennmaradó fordítóhibák kijavításához:
SensorMeasurement measure = default;
Most, hogy a fordító hibáinak elhárítása megtörtént, meg kell vizsgálnia a kódot, hogy a szemantika ne változzon. Mivel struct
a típusok érték szerint vannak átadva, a metódusparaméterek módosításai nem láthatók a metódus visszatérése után.
Fontos
Ha egy típust a típusról class
a másikra struct
módosít, az megváltoztathatja a program szemantikáját. Amikor egy típust class
átadnak egy metódusnak, a metódusban végrehajtott összes mutáció az argumentumra kerül. Amikor egy típust struct
átad egy metódusnak, és a metódusban végrehajtott mutációk az argumentum egy példányára kerülnek. Ez azt jelenti, hogy minden olyan metódust, amely az argumentumait terv szerint módosítja, frissíteni kell, hogy a ref
módosító az a-ról a-ra class
módosult bármely argumentumtípuson használható legyen struct
.
A SensorMeasurement
típus nem tartalmaz olyan metódusokat, amelyek módosítják az állapotot, ezért ez ebben a mintában nem okoz problémát. Ezt bizonyítja, ha hozzáadja a readonly
módosítót a SensorMeasurement
szerkezethez:
public readonly struct SensorMeasurement
A fordító kikényszeríti a readonly
szerkezet természetét SensorMeasurement
. Ha a kód ellenőrzése kihagyott egy módosított metódust, a fordító közli. Az alkalmazás továbbra is hibák nélkül épül fel, így ez a típus a következő readonly
: . A módosító hozzáadása a readonly
típusról class
a típusra struct
való váltáskor segíthet megtalálni azokat a tagokat, amelyek módosítják az struct
állapotot.
Kerülje a másolatkészítést
Számos szükségtelen foglalást eltávolított az alkalmazásból. A SensorMeasurement
típus sehol nem jelenik meg a táblázatban.
Most még több munkát végez a SensorMeasurement
struktúra másolásán minden alkalommal, amikor paraméterként vagy visszatérési értékként használják. A SensorMeasurement
szerkezet négy dupla, egy DateTime és egy string
. Ez a struktúra mérhetően nagyobb, mint egy hivatkozás. Vegyük fel a ref
módosítókat az in
olyan helyekre, ahol a SensorMeasurement
típust használjuk.
A következő lépés a mérést visszaadó metódusok megkeresése, vagy a mérés argumentumként való használata, valamint a hivatkozások használata, ahol lehetséges. Kezdje a SensorMeasurement
szerkezetben. A statikus TakeMeasurement
metódus létrehoz és visszaad egy újat SensorMeasurement
:
public static SensorMeasurement TakeMeasurement(string room, int intruders)
{
return new SensorMeasurement
{
CO2 = (CO2Concentration + intruders * 10) + (20 * generator.NextDouble() - 10.0),
O2 = (O2Concentration - intruders * 0.01) + (0.005 * generator.NextDouble() - 0.0025),
Temperature = (TemperatureSetting + intruders * 0.05) + (0.5 * generator.NextDouble() - 0.25),
Humidity = (HumiditySetting + intruders * 0.005) + (0.20 * generator.NextDouble() - 0.10),
Room = room,
TimeRecorded = DateTime.Now
};
}
Ezt úgy fogjuk hagyni, ahogy van, érték szerint visszaadva. Ha megpróbál visszatérni ref
, fordítóhiba jelenik meg. A metódusban helyileg létrehozott új struktúrába nem térhet vissza ref
. A nem módosítható szerkezet kialakítása azt jelenti, hogy csak az építéskor állíthatja be a mérés értékeit. Ennek a módszernek létre kell hoznia egy új mérési szerkezetet.
Vizsgáljuk meg újra.DebounceMeasurement.AddMeasurement
Adja hozzá a in
módosítót a measurement
paraméterhez:
public void AddMeasurement(in SensorMeasurement datum)
{
int index = totalMeasurements % debounceSize;
recentMeasurements[index] = datum;
totalMeasurements++;
double sumCO2 = 0;
double sumO2 = 0;
double sumTemp = 0;
double sumHumidity = 0;
for (int i = 0; i < debounceSize; i++)
{
if (recentMeasurements[i].Room is not null)
{
sumCO2 += recentMeasurements[i].CO2;
sumO2+= recentMeasurements[i].O2;
sumTemp+= recentMeasurements[i].Temperature;
sumHumidity += recentMeasurements[i].Humidity;
}
}
O2 = sumO2 / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
CO2 = sumCO2 / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
Temperature = sumTemp / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
Humidity = sumHumidity / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
}
Ez egy másolási műveletet ment. A in
paraméter a hívó által már létrehozott másolatra mutató hivatkozás. A példányt a típus metódusával TakeMeasurement
Room
is mentheti. Ez a módszer bemutatja, hogy a fordító hogyan biztosítja a biztonságot, ha argumentumokat ref
ad át. A típus kezdeti TakeMeasurement
metódusa a Room
következő argumentumot Func<SensorMeasurement, bool>
veszi fel: . Ha megpróbálja hozzáadni a vagy ref
módosítót a in
deklarációhoz, a fordító hibát jelez. Nem adhat át argumentumot ref
lambdakifejezésnek. A fordító nem tudja garantálni, hogy a hívott kifejezés nem másolja a hivatkozást. Ha a lambda kifejezés rögzíti a hivatkozást, a hivatkozás élettartama hosszabb lehet, mint a hivatkozott érték. Ha a ref biztonságos környezetén kívülre fér hozzá, memóriasérülést okozna. A ref
biztonsági szabályok nem teszik lehetővé. A ref biztonsági funkcióinak áttekintésében többet is megtudhat.
Szemantikák megőrzése
A végleges módosításkészletek nem befolyásolják nagy mértékben az alkalmazás teljesítményét, mert a típusok nem gyakori elérésű útvonalakon jönnek létre. Ezek a módosítások a teljesítményhangolásban használt egyéb technikák némelyikét szemléltetik. Tekintsük meg a kezdeti Room
osztályt:
public class Room
{
public AverageMeasurement Average { get; } = new ();
public DebounceMeasurement Debounce { get; } = new ();
public string Name { get; }
public IntruderRisk RiskStatus
{
get
{
var CO2Variance = (Debounce.CO2 - Average.CO2) > 10.0 / 4;
var O2Variance = (Average.O2 - Debounce.O2) > 0.005 / 4.0;
var TempVariance = (Debounce.Temperature - Average.Temperature) > 0.05 / 4.0;
var HumidityVariance = (Debounce.Humidity - Average.Humidity) > 0.20 / 4;
IntruderRisk risk = IntruderRisk.None;
if (CO2Variance) { risk++; }
if (O2Variance) { risk++; }
if (TempVariance) { risk++; }
if (HumidityVariance) { risk++; }
return risk;
}
}
public int Intruders { get; set; }
public Room(string name)
{
Name = name;
}
public void TakeMeasurements(Func<SensorMeasurement, bool> MeasurementHandler)
{
SensorMeasurement? measure = default;
do {
measure = SensorMeasurement.TakeMeasurement(Name, Intruders);
Average.AddMeasurement(measure);
Debounce.AddMeasurement(measure);
} while (MeasurementHandler(measure));
}
}
Ez a típus több tulajdonságot is tartalmaz. Néhány típus class
. Egy Room
objektum létrehozása több foglalást is magában foglal. Egyet önmagáért Room
, egyet pedig egy-egy class
a benne található típus minden egyes tagjára. A tulajdonságok közül kettő típusról class
típusra struct
alakítható át: a típusokra és AverageMeasurement
a DebounceMeasurement
típusokra. Vizsgáljuk meg ezt az átalakítást mindkét típussal.
Módosítsa a típust DebounceMeasurement
a következőrestruct
: aclass
. Ez egy fordítóhibát CS8983: A 'struct' with field initializers must include an explicitly declared constructor
eredményez. Ezt egy üres paraméter nélküli konstruktor hozzáadásával javíthatja:
public DebounceMeasurement() { }
Erről a követelményről a szerkezetekről szóló nyelvi referenciacikkben tudhat meg többet.
A Object.ToString() felülbírálás nem módosítja a szerkezet egyik értékét sem. A módosító hozzáadható a readonly
metódusdeklarációhoz. A DebounceMeasurement
típus nem módosítható, ezért gondoskodnia kell arról, hogy a módosítások ne befolyásolják az elvetett másolatokat. A AddMeasurement
metódus módosítja az objektum állapotát. A metódus az Room
osztályból van meghívva TakeMeasurements
. A metódus meghívása után is meg szeretné őrizni ezeket a módosításokat. A tulajdonságot módosíthatja úgyRoom.Debounce
, hogy a típus egyetlen példányára DebounceMeasurement
mutató hivatkozást adjon vissza:
private DebounceMeasurement debounce = new();
public ref readonly DebounceMeasurement Debounce { get { return ref debounce; } }
Az előző példában van néhány változás. Először is a tulajdonság egy olvasható tulajdonság, amely a helyiség tulajdonában lévő példányra mutató, olvasható hivatkozást ad vissza. Most már egy deklarált mező is alátámasztja, amely inicializálva van az Room
objektum példányosításakor. A módosítások elvégzése után frissíteni fogja a metódus implementálását AddMeasurement
. A privát háttérmezőt használja, debounce
nem az olvasható tulajdonságot Debounce
. Így a módosítások az inicializálás során létrehozott egyetlen példányon történnek.
Ugyanez a technika működik a Average
tulajdonsággal. Először módosítsa a típust egyről AverageMeasurement
egyre class
struct
, majd adja hozzá a readonly
módosítót a ToString
metódushoz:
namespace IntruderAlert;
public struct AverageMeasurement
{
private double sumCO2 = 0;
private double sumO2 = 0;
private double sumTemperature = 0;
private double sumHumidity = 0;
private int totalMeasurements = 0;
public AverageMeasurement() { }
public readonly double CO2 => sumCO2 / totalMeasurements;
public readonly double O2 => sumO2 / totalMeasurements;
public readonly double Temperature => sumTemperature / totalMeasurements;
public readonly double Humidity => sumHumidity / totalMeasurements;
public void AddMeasurement(in SensorMeasurement datum)
{
totalMeasurements++;
sumCO2 += datum.CO2;
sumO2 += datum.O2;
sumTemperature += datum.Temperature;
sumHumidity+= datum.Humidity;
}
public readonly override string ToString() => $"""
Average measurements:
Temp: {Temperature:F3}
Humidity: {Humidity:P3}
Oxygen: {O2:P3}
CO2 (ppm): {CO2:F3}
""";
}
Ezután a Room
tulajdonsághoz használt technikát követve módosítja az osztályt Debounce
. A Average
tulajdonság egy értéket ad vissza readonly ref
a magánmezőbe az átlagos méréshez. A AddMeasurement
metódus módosítja a belső mezőket.
private AverageMeasurement average = new();
public ref readonly AverageMeasurement Average { get { return ref average; } }
Kerülje a boxolást
A teljesítmény javítása érdekében van még egy utolsó változás. A fő program a szoba statisztikáinak nyomtatása, beleértve a kockázatértékelést:
Console.WriteLine($"Current intruders: {room.Intruders}");
Console.WriteLine($"Calculated intruder risk: {room.RiskStatus}");
A generált ToString
hívás az enumerálás értékét adja meg. Ezt elkerülheti, ha felülbírálást ír az Room
osztályba, amely a becsült kockázat értéke alapján formázza a sztringet:
public override string ToString() =>
$"Calculated intruder risk: {RiskStatus switch
{
IntruderRisk.None => "None",
IntruderRisk.Low => "Low",
IntruderRisk.Medium => "Medium",
IntruderRisk.High => "High",
IntruderRisk.Extreme => "Extreme",
_ => "Error!"
}}, Current intruders: {Intruders.ToString()}";
Ezután módosítsa a kódot a fő programban az új ToString
metódus meghívásához:
Console.WriteLine(room.ToString());
Futtassa az alkalmazást a profilkészítővel, és tekintse meg a foglalások frissített tábláját.
Számos foglalást eltávolított, és teljesítménynövelő funkciót biztosított az alkalmazásnak.
Ref-biztonság használata az alkalmazásban
Ezek a technikák alacsony szintű teljesítményhangolást jelentenek. Növelhetik az alkalmazás teljesítményét a gyakori elérésű útvonalakra alkalmazva, valamint a módosítások előtti és utáni hatás mérésére. A legtöbb esetben a következő ciklust fogja követni:
- Mértékfoglalások: Határozza meg, hogy mely típusok vannak a leginkább lefoglalva, és mikor lehet csökkenteni a halomfoglalásokat.
- Osztály átalakítása strukturálttá: A típusok sokszor átalakíthatók egy
class
osztályból egybestruct
. Az alkalmazás veremterületet használ a halomfoglalások helyett. - Szemantikák megőrzése: Az a
class
struct
paraméter átalakítása hatással lehet a paraméterek szemantikára, és visszaadhatja az értékeket. Minden olyan metódusnak, amely módosítja a paramétereit, most már meg kell jelölnie ezeket a paramétereket aref
módosítóval. Ez biztosítja, hogy a módosítások a megfelelő objektumon legyenek elvégezve. Hasonlóképpen, ha a hívónak módosítania kell egy tulajdonság vagy metódus visszatérési értékét, a visszatérést aref
módosítóval kell megjelölni. - Kerülje a másolást: Ha egy nagy szerkezetet ad át paraméterként, a módosítóval megjelölheti a
in
paramétert. Kevesebb bájtban adhat át egy hivatkozást, és győződjön meg arról, hogy a metódus nem módosítja az eredeti értéket. Az értékeketreadonly ref
úgy is visszaadhatja, hogy olyan hivatkozást ad vissza, amely nem módosítható.
Ezekkel a technikákkal javíthatja a teljesítményt a kód gyakori elérési útjaiban.