Ref Returns, Ref Locals, Ref Arg

Powracamy do podstaw, tak – dla sportu.

Przekazywanie zmiennej typu wartościowego, takiej jak int czy czy struct do metody przez referencję oraz zwracanie wartości z metody przez referencję to coś, co rzadko wykorzystuje się na co dzień, dlatego od czasu do czasu warto odświeżyć sobie tę wiedzę.

W załączonym kodzie możesz prześledzić różnice między przekazywaniem argumentów przez wartość oraz przez referencję. Przedstawiam przykłady przekazywania typów wartościowych oraz referencyjnych jako argumenty do metod i modyfikowania ich wartości wewnątrz metod.

Przed przejściem do kodu, należy pamiętać, że przekazywanie zmiennych przez referencję może prowadzić do trudniejszego zrozumienia kodu i jego debugowania. Dlatego należy zachować ostrożność i rozważyć odpowiednio użycie tej techniki.

Program wyświetli wartości zmiennych przed i po przekazaniu ich jako argument do metod. Ilustruje różnice między przekazywaniem przez wartość i przez referencję, a także wpływ modyfikowania wartości argumentów wewnątrz metod.

GitHub: Ref Arg

// Przejdź do GitHub, aby przeanalizować całość kodu
// wraz z wydrukowanymi wynikami i komentarzami
 
var globalInt = 100;
ArgIntMethod(globalInt);
ArgRefIntMethod(ref globalInt);

var globalStruct = new FirstStruct { /***/};
ArgStructMethod(globalStruct);
ArgRefStructMethod(ref globalStruct);

var globalClass = new Class { /***/};
EditPropsOfArgClassMethod(globalClass);
EditPropsOfArgRefClassMethod(ref globalClass);

Przedstawiłem również przykłady zwracania z metody typów wartościowych oraz referencyjnych przez referencję oraz ich przypisanie do lokalnych referencyjnych typów wartościowych.

GitHub: Ref Locals, Ref Returns

// Przejdź do GitHub, aby przeanalizować całość kodu
// wraz z wydrukowanymi wynikami i komentarzami

var globalClassObject = new Class();
var value = globalClassObject.GetInt();
value += 100;

ref var localRef = ref globalClassObject.RefGetInt();
localRef += 100;

var localValueType = globalClassObject.RefGetInt();
localValueType += 1000;

var complexObject = new Object();
var dto = complexObject.GetDto();
dto.IntProp += 111;
dto = new Dto { IntProp = 1_000 };

ref var refDto = ref complexObject.RefGetDto();
refDto = new Dto { IntProp = 5_000_000 };

internal class Class
{
    private int _valueTypeVariable = 100;

    public int GetInt() => _valueTypeVariable;
    public ref int RefGetInt() => ref _valueTypeVariable;
}

internal class Object
{
    private Dto _dto = new ();

    public Dto GetDto() =>_dto;
    public ref Dto RefGetDto() => ref _dto;
}

internal class Dto
{
    public int IntProp { get; set; } = 111;
}

Przekazując do metody zmienną typu wartościowego, jej wartość nie jest trwale zmodyfikowana poza tą metodą. Natomiast, gdy przekazujemy je przez referencję, jej wartość może zostać zmodyfikowana wewnątrz metody, co będzie miało wpływ na jej wartość poza metodą.

Podsumowując, gdy potrzebujemy zoptymalizować wydajność swojej aplikacji, czasami lepiej jest używać typów wartościowych, zamiast typów referencyjnych. Powodem jest to, że typy wartościowe są przechowywane na stosie, a nie na starcie, co oznacza, że GC ma mniej pracy, ponieważ nie musi śledzić i czyścić nieużywanych obiektów.

Kolejnym sposobem na poprawienie wydajności programu jest przekazywanie typów wartościowych przez referencję. Unikamy w ten sposób nadmiaru kopiowania wartości do zasięgu lokalnego metody, zwłaszcza gdy pracujemy z dużymi wartościowymi lub często wywołujemy metodę.

Pamiętajcie, że przekazywanie argumentów przez referencję może być użyteczne w celu poprawienia wydajności, ale należy zachować ostrożność i rozważyć, czy jest to odpowiednie dla danego przypadku.

P.S. Większą część tekstu na blogu i w GitHub oraz komentarze w kodzie wygenerował za mnie ChatGPT (nie wiem, czy chciałoby mi się to wszystko pisać samemu xD).

Prostota - Edsger Dijkstra

Prostota jest wielką zaletą

Prostota jest wielką zaletą, ale wymaga ciężkiej pracy, aby ją osiągnąć, i edukacji, aby ją docenić. Co gorsza, złożoność lepiej się sprzedaje.”

Edsger Dijkstra


Niedawno Boiling Frongs wypuścili nowe, fajne nagranie.

Sentencja jest zwięzła i gdyby się nad nią dłużej zastanowić, niesie za sobą olbrzymią ilość treści. Cała prelekcja jest bardzo dobra, a niżej linkuję do fragmentu który szczególnie mi się spodobał.

Boiling Frogs 2021 Jacek Lempart – Realizuj projekty oparte na pasji

If you’re good at the debugger it means you spent a lot of time debugging. I don’t want you to be good at the debugger.

Robert C. Martin

Ja nie mam czasu nie pisać testów jednostkowych

Czasami (czasami często) słyszę, że:

…ktoś nie napisał testu jednostkowego bo nie miał na to czasu.

Gdy to słyszę to aż bolą mnie zęby. Jak można nie mieć czasu na sprawdzenie, czy nasz kod działa poprawnie? Wtedy zawsze staram się wyjaśnić, że:

… ja nie mam czasu nie pisać testów jednostkowych.

Continue reading →

Poziomy abstrakcji

Kilka lat temu, ucząc się programowania w języku C++, natknąłem się na ten tekst.

„Komputery są jedynie urządzeniami elektronicznymi. Nie mają pojęcia o oknach czy menu, nie znają programów ani instrukcji, a nawet nie wiedzą nic o zerach i jedynkach. W rzeczywistości jedyne zmiany, jakie zauważają, to zmiany napięcia mierzonego w odpowiednich punktach układów elektronicznych. Nawet to jest dla nich pewną abstrakcją: w rzeczywistości elektryczność jest tylko wygodną intelektualną koncepcją dla zaprezentowania działania cząstek subatomowych, które z kolei są abstrakcją dla czegoś innego.”

„C++ dla każdego” Jesse Liberty

 

Kalkulator napisany z pomocą behavior-driven development (BDD)

Postawiłem sobie za cel napisanie kalkulatora przy użyciu metody BDD a wynikami mojej pracy chcę się z wami podzielić.

Kalkulator ten będzie zachowywać się jak ten z lat dziewięćdziesiątych, pokazany poniżej na obrazku. Mam jeszcze taki sam w domu — ma już chyba 20 lat. Ten, który tutaj zaimplementuje, będzie posiadał, tak samo, jak ten oryginalny, kilka dziwnych zachowań. Na przykład, przy każdym ponownym wciśnięciu „=”, liczba na wyświetlaczu będzie się zwiększać o jeden, jeśli wcześniej wykonaliśmy działanie „1+1”.

Continue reading →