Małe ulepszenia codu w C#

Enumerable.Empty

Jeśli funkcja zwraca IEnumerable, nie zwracaj pustej dopiero co stworzonej listy. Enumerable.Empty() jest właśnie tym czego oczekuje wywołujący kod.

return new MyClass[0];

// Better
return Enumerable.Empty<MyClass>();

Operator ??

Dwa poniższe kawałki kodu są równoważne. Drugi jest w tym przypadku czytelniejszy, widzimy od razu, że chodzi o ‚tzw’ fallback.

return item.ColorInHex != null ? item.ColorInHex : "#FF0000";

// Better
return item.ColorInHex ?? "#FF0000";

// Side note: don't hardcode values, constants are better choice
return item.ColorInHex ?? MyClass.UnknownColorInHex;

Invert ‚if’ to reduce nesting

Staraj się szybko wychodzić z funkcji, unikasz słabo czytelnych wcięć.

if (item != null)
{
    if (item.ColorInHex != null)
    {
        var colorName = GetColorName(item.ColorInHex);
        return colorName;
    }
}
return null;

// Return (end method) as you are ready, reduce nesting
if (item == null)
    return null;

if (item.ColorInHex == null)
    return null;

var colorName = GetColorName(item.ColorInHex);
return colorName;

Linq w wielu liniach

Czytelne formatowanie to ciężki temat do standaryzacji, ale wg mnie ostatni przykład jest najbardziej czytelny.

// Too long
return items.Where(item => item.ColorInHex != null).OrderBy(item => item.ColorInHex).Select(item => new MyColor(item.ColorInHex));

// Even worse, done automatically by Resharper to meet max characters in the line requirement
return items.Where(item => item.ColorInHex != null).OrderBy(item => item.ColorInHex).Select(
    item => new MyColor(item.ColorInHex));

// Maybe not perfect, but more readable
return items
    .Where(item => item.ColorInHex != null)
    .OrderBy(item => item.ColorInHex)
    .Select(item => new MyColor(item.ColorInHex));
Reklamy
Ten wpis został opublikowany w kategorii Programowanie i oznaczony tagami , , . Dodaj zakładkę do bezpośredniego odnośnika.

13 odpowiedzi na „Małe ulepszenia codu w C#

  1. Pingback: dotnetomaniak.pl

  2. Paweł pisze:

    Odnośnie Linq w zbyt wielu polach: często dobrym wyjściem jest utworzenie metody prywatnej zawierającej tylko to wyrażenie i nazwanie jej w dużo mówiący sposób. Łatwiej czytać taki kod, niż zastanawiać się co autor Linq miał na myśli i co chciał osiągnąć.

  3. @Paweł, myślisz o metodzie prywatnej na tylko jedno wyrażenie LINQ czy też na wiele wyrażeń (jak u mnie 3 w przykładzie)?

  4. Pawel2 pisze:

    Dlaczego uważasz, że zwrócenie Enumerable.Empty() jest lepsze od pustej tablicy?

  5. Trochę parafrazując to co napisałem oryginalnie: twój kod jasno wskazuje na twoje intencje. Dopiero na drugim miejscu jest też lepsze wydajnościowo, jako że wynik zwracany przez Empty() jest cachowany.
    http://stackoverflow.com/questions/5319930/which-is-better-enumerable-emptyt-or-new0

    • Pawel2 pisze:

      Co do 2) zgadzam się.
      A co do 1) dla mnie właśnie zwrócenie pustej tablicy jest bardziej czytelne. Jak widzę Empty() to od razu mam ochotę wcisnąć F12 i zobaczyć co tam w środku jest zwracane (teraz już wiem). Moim zdaniem to taka sama dyskusja jak: http://stackoverflow.com/questions/263191/in-c-should-i-use-string-empty-or-string-empty-or

      Kwestia gustu 🙂

    • kmorawski pisze:

      Też akurat nie znałem tego Enumerable.Empty, ale podoba mi się. Skoro należy do systemowych bibliotek .NET, to programista powinien je rozpoznawać, a tę wiedzę trzeba zdobyć tylko raz 🙂

      Pusta tablica – to taki trochę hack (bo czemu zwracać właśnie tablicę a np. nie listę?).

      Ogólna zasada jest tutaj wg mnie taka, żeby zawsze używać możliwie najbardziej pierwotnego typu. Zatem jeśli wystarczy zwrócić IEnumerable, to nie trzeba zwracać T[] ani List (mimo że można). To samo dotyczy typu argumentów w metodach.

  6. Według mnie to jednak jest trochę inna dyskusja. Czy string.Empty czy „” wygeneruje ten sam kod. i jest rzeczywiście dyskusyjne (troche flame war) co jest czytelniejsze.
    W przypadku Empty() a new MyClass[] jest jednak inny kod generowany i przynajmniej na stackoverflow ludzie uważają ten pierwszy za bardziej czytelny.
    @Pawel2 Ale gdy się tak na tym dobrze zastanowię to nie potrafię dobrze wytłumaczyć dlaczego jest bardziej czytelne. Po prostu kiedyś gdzieś przeczytałem (zobaczyłem, ktoś mi powiedział – nie pamiętam), że tak jest czytelniej i po prostu tak robię.

  7. @Krzysiek – nawet dla jednego wyrażenia LINQ. Problem jest taki, że czasem widać wyrażenie, którego celu nie da się wyjaśnić na pierwszy rzut oka. Zatrzymujesz się, czytając taki kod, i starasz się dojść – o co chodzi? O ile lepsze w takim wypadku jest wywołanie metody z nazwą wyrażającą intencję twórcy.

    • kmorawski pisze:

      Jeżeli chodzi tylko o jedno wyrażenie, to zamiast od razu robić metodę, wystarczy wg mnie stworzyć zmienną tymczasową (o zrozumiałej nazwie)

    • @kmorawski: A tutaj już zależy – raczej staram się nie mieszać poziomów abstrakcji. Jeżeli w metodzie są wywołania innych metod, to lepiej wg mnie to wyrażenie LINQ umieścić jednak w innej metodzie. Jeżeli metoda zawiera jednak „mechanikę”, to wtedy także zdecydowałbym się na Twój sposób ze zmienną.

  8. Jeśli się nie da, to trudno – nic tutaj nie wymyślę. Jak trzeba to trzeba 😉 W zdecydowanej większości przypadków, jeśli robię Select(p => new MyClass(p)) to widać w kodzie po co to jest. Podobnie. z OfType, OrderBy, Skip, Take itp.

  9. Pingback: Coding News 06.11.2013 - codingtv(); - video-blog programistyczny

Możliwość komentowania jest wyłączona.