Czytelniejszy kod C# dzięki argumentom nazwanym (ang. named arguments)

Standard C# 4.0 wprowadził tzw. argumenty nazwane (ang. named arguments), które pozwalają na identyfikowanie argumentów wywołania funkcji za pomocą nazw, a nie kolejności w definicji. Wyobraźmy sobie że mamy daną metodę:

public int Sum(int arg1, int arg2, int arg3)
{
   return arg1 + arg2 + arg3;
}

Możemy ją wywołać jawnie deklarując wartości dla argumentów, nie zwracając uwagi na ich kolejność:

int result = Add(arg2: 5, arg1: 4, arg3: 0) // returns 9

Możemy również pomieszać wywołanie argumentów z konkretnej pozycji z argumentami nazwanymi, o ile te drugie wystąpią na końcu:

int result = Add(5, arg2: 4, arg3: 0) // returns 9

Powyższy przykład nie przynosi jednak zbyt wielkich korzyści dla programisty czytającego ten kod. Wyobraźmy sobie jednak takie wywołanie metody:

SendHttpMessage(header, message, false);

O ile przeznaczenia dwóch pierwszych argumentów można się domyśleć, o tyle nie wiadomo, dlaczego przekazywana jest wartość false. Powiedzmy że powyższe wywołanie tyczy się takiej metody:

public void SendHttpMessage(string header, string message, bool debug)
{
 ... // some code here
}

Korzystając z argumentów nazwanych, można tę metodę wywołać w taki sposób:

SendHttpMessage(header, message, debug: false);

Teraz przeglądając kod zawierający takie wywołanie, programista nie będzie musiał dodatkowo przeglądać definicje metody, aby w pełni ją zrozumieć. Argumenty nazwane doskonale sprawdzają się również przy definiowaniu warunków w testach jednostkowych. Wyobraźmy sobie taki test:

[Fact]
public void Should_Properly_Calculate_Sum()
{
   var sut = new PowerfulSum();
   var result = sut.Sum(5, 5);
   Assert.Equal(result, 10);
}

Na pierwszy rzut oka test wydaje się czytelny, nawet jest zmienna result, dzięki której patrząc na metodę Assert.Equal() wiemy, gdzie jest wynik działania. Jednak mija trochę czasu, zmieniamy kod, a tu nagle test nie przechodzi:

No to zaczynamy szukać błędu, może nie przyjrzeliśmy się samemu testowi, tylko zaczynamy od debugowania metody, idziemy krok po kroku, wynik operacji: 9. W opisie testu, wynik oczekiwany: 9. Gdzie jest błąd? Okazuje się że zgodnie z definicją metody Assert.Equal(), argumenty powinny mieć odwrotną kolejność.

public void Assert.Equal<int>(int expected, int actual);
</int>

Oczywiście, koniec końców uda nam się znaleźć błąd. Ale zwykłe przeoczenie i zaczynamy niepotrzebnie tracić czas. Można taki test zdefiniować nieco czytelniej:

[Fact]
public void Should_Properly_Calculate_Sum()
{
   var sut = new PowerfulSum();
   var result = sut.Sum(5, 5);
   Assert.Equal(expected: 10, actual: result);
}

Podsumowując, argumenty nazwane w wywołaniach metod mogą zwiększyć czytelność naszego kodu, co może przełożyć się na mniejszą liczbę błędów.

Bibliografia

  1. J. Albahari, B. Albahari, „C# 6.0 w pigułce. Wydanie VI”. 1. Wprowadzenie do C# i .NET Framework, s. 24
  2. Named and Optional Arguments (C# Programming Guide)