Kiedy „Try” powinno być używane w nazwach metod C #?

180

Dyskutowaliśmy z naszymi współpracownikami, co to znaczy, jeśli nazwa metody zaczyna się od „Try”.

Były następujące opinie:

  • Użyj „Spróbuj”, gdy metoda może zwrócić wartość pustą.
  • Użyj „Spróbuj”, gdy metoda nie zgłosi wyjątku.

Jaka jest oficjalna definicja? Co mówi „Try” w nazwie metody? Czy istnieją jakieś oficjalne wytyczne na ten temat?

ms007
źródło
83
+1 Ludzie, którzy tak długo zastanawiają się nad nazwami swoich funkcji, faktycznie szukają „następnego faceta”. Nie wiem, dlaczego to jest już blisko głosów (i to pochodzących z facetem, który obsadził wiele z nich dzisiaj.)
Jonathon Reinhart
7
@JonathonReinhart, uzyskał bliskie głosy, ponieważ „W obecnym stanie pytanie to nie pasuje do naszego formatu pytań i odpowiedzi. Oczekujemy, że odpowiedzi będą poparte faktami, referencjami lub specjalistyczną wiedzą, ale to pytanie prawdopodobnie zachęci do debaty, argumentów , ankietę lub rozszerzoną dyskusję ”.
Pranav Hosangadi
16
Nie jest to oficjalna wypowiedź Microsoft, która odpowiada na pytanie (patrz moja odpowiedź). Jak to nie jest faktem?
Erik Schierboom
6
@PranavHosangadi, jak wspomniał Erik, jest to poparte faktami. Ponadto, jest tu wielu bardzo doświadczonych programistów C #, którzy dysponują specjalistyczną wiedzą, aby udzielić prawidłowej odpowiedzi. Do diabła, Eric Lippert jest głównym architektem języka C #. Myślę, że można nazwać to konkretną wiedzą specjalistyczną .
Jonathon Reinhart
4
@ErikSchierboom Że to wytyczna MS to fakt. To, że wytyczna MS jest właściwą wytyczną, jest subiektywna i dyskusyjna.
Servy

Odpowiedzi:

148

Jest to znane jako wzorzec TryParse i zostało udokumentowane przez Microsoft. W oficjalnych Wyjątki i wydajności stronę MSDN mówi :

Rozważ wzorzec TryParse dla członków, którzy mogą zgłaszać wyjątki w typowych scenariuszach, aby uniknąć problemów z wydajnością związanych z wyjątkami.

Zatem jeśli masz kod, dla którego zwykły przypadek użycia oznaczałby, że może zgłosić wyjątek (taki jak parsowanie liczby całkowitej ), wzorzec TryParse ma sens.

Erik Schierboom
źródło
2
Kolejny przydatny link, który dokumentuje ten wzorzec (poszukiwanie TryParse) blogs.msdn.com/b/kcwalina/archive/2005/03/16/396787.aspx
Vivek
2
Zasadniczo, jeśli masz metodę TryParse, powinieneś mieć metodę Parse, która wyrzuca, gdy TryParse zwróci false. I odwrotnie, jeśli masz metodę Parse, powinieneś rozważyć zastosowanie metody TryParse, która zwróci wartość false, gdy Parse rzuci
3Doubloons
5
+1. Dodajmy do tego, że wyjątki dotyczą zazwyczaj „wyjątkowych” okoliczności. Jeśli robisz coś, co może łatwo zawieść i że awaria nie jest szczególnie godne uwagi, a następnie za pomocą tego wzoru jest bardziej idiomatyczne niż try / catch
Adam Robinson
Czy taki wzór naprawdę wymagał wskazówek od Microsoft? Wydaje się to dość podstawowe rzeczy.
Dave Lawrence
19
To jest podstawowe rzeczy, ale to nie znaczy, że wytyczne nie są użyteczne. Właściwe przygotowanie podstawowych rzeczy może być dość trudne, jeśli nie znasz wystarczająco platformy.
Erik Schierboom
119

(Poprawiony) Istnieje oficjalna wytyczna, jak sugerował Erik.

Kiedy widzę TrySomethingmetodę, zakładam, że

  • nie rzuca
  • zwroty bool
  • jeśli oczekuję wartości, jest ona zwracana za pomocą parametru „out”
  • istnieje Somethingmetoda, która pozwala mi samodzielnie obsłużyć każdy wyjątek. (edycja sugerowana przez Jesse Webb)
nic
źródło
4
Korekta - ma oficjalne wytyczne. Zobacz odpowiedź Erika.
nothrow
8
+1 Ale mam również czwarte oczekiwanie: jeśli istnieje TryFoometoda, będzie podobna Foometoda, która pozwoli mi poradzić sobie z wszelkimi `` wyjątkami ''. Podpisy tych metod będą prawdopodobnie różne, więc ich zastosowania nie będą zamienne bez innych zmian w kodzie.
Jesse Webb,
1
@JesseWebb, dzięki za zwrócenie na to uwagi. Dodałem twój komentarz do mojej odpowiedzi, jeśli nie masz nic przeciwko.
nothrow
1
„Nie rzuca” wydaje mi się zbyt ogólne. Na przykład Int32.TryParse (String, NumberStyles, IFormatProvider, Int32) zgłasza ArgumentException, jeśli nie podoba mu się parametr stylu.
Jirka Hanika
Zgadzam się, że „nie rzuca” można uznać za nadmiernie uogólnione, ale uważam, że intencją było przekazanie, że nie rzuca się to w wyniku wykonania, a nie w wyniku wartości parametrów.
ConfusingBoat
8

Myślę, że powinieneś użyć, trykiedy chcesz kontynuować. Nie ma znaczenia, że ​​metoda zwraca pewną wartość, czy nie.

Przypadek 1: jeśli zwróci się dobrze, możesz postępować w jakiś sposób.

Przypadek 2: jeśli nie zwróci: nadal jest w porządku; możesz postępować w inny sposób.

A jeśli oczekujesz pewnej wartości jako wyniku tej metody, użyj outparametru.

Przykład

int value
if (dictionary.TryGetValue("key", out value))
{
    // Proceed in some way
}
else
{
    // Proceed in some other way
}
Ashok Damani
źródło
6

Musisz użyć „Try” w nazwie metody, jeśli chcesz zamanifestować fakt, że wywołanie metody może dać niepoprawny wynik. Nawiasem mówiąc, zgodnie ze standardem .NET nie jest to funkcja, która wywołuje wyjątek, ale funkcja, która zwraca część VALIDlub NON_VALID, z perspektywy programu, wartość.

Na koniec chodzi o konwencję nazewnictwa, którą zdecydujesz się zastosować w swojej grupie.

Tigran
źródło
5

Pamiętaj o dołączeniu do trynazwy metody, jeśli:

  • nie rzucasz żadnych wyjątków
  • twoja metoda ma następujący podpis: bool TrySomething(input, out yourReturn)

Zasadniczo, jeśli użyjemy try-metod, otrzymamy tylko wynik boolowski.

Poniższy kod nie zgłosi żadnych wyjątków:

string input = "blabla";
int number;
if (int.TryParse(input, out number))
{
// wooohooo we got an int!
} else
{
//dooh!
}

Podczas gdy ten kod może (iw tym przypadku będzie) zgłaszać wyjątki:

string input = "blabla";
int number;
try
{
     number = int.Parse(input); //throws an exception
}
catch (Exception)
{
     //dooh!
}

Korzystanie z metod Try jest bezpieczniejszym i bardziej defensywnym sposobem kodowania. Fragment kodu nr 2 wymaga większej wydajności, jeśli nie jest liczbą całkowitą.

Fabian Bigler
źródło
Fragment kodu nr 2 powinien zostać odczytany, int number = int.Parse(input);jeśli chcesz, aby był bardziej znaczący w tym kontekście.
Pierre Arnaud,
@PierreArnaud Dzięki, zmieniłem to!
Fabian Bigler,
Wciąż brakuje int number;deklaracji przed blokiem try i number = ...przypisaniem.
Pierre Arnaud
@PierreArnaud Dziękuję, dołączyłem teraz także „int number”.
Fabian Bigler
Pamiętaj, że nadal możesz zgłaszać wyjątki, jeśli wyjątek jest w pewnym stopniu niezwiązany z wykonywaną akcją bezpośrednią, taką jak TryLoadFile(path, out file)woah, poza pamięcią RAM. Osoba dzwoniąca nie spodziewałaby się więc żadnych błędów w przypadku złej ścieżki lub odmowy dostępu, ale wyjątek dla dziwniejszych rzeczy, które również mogłyby pójść nie tak. I udokumentuj to.
Luke Puplett
0

Wujek Bob podaje poniższy przykład w swojej książce Clean Code . Ilekroć spodziewamy się zgłoszenia wyjątku, możemy użyć Tryprefiksu nazwy metody:

public void sendShutDown()
{
    try{
        tryToShutDown();
    } catch (DeviceShutDownError e) {
        logger.log(e);            
    }
}

A następnie (dostosowany):

private void tryToShutDown()
{
    //some code with no error handling, but
    //something might go wrong here
}

tryToShutDownMetoda nie ma żadnej obsługi błędów, bo to w gestii sendShutDownmetody.

The TryParseWzór Microsoft narusza czystego kodu wytyczna, która mówi, że powinniśmy unikać parametry wyjściowe.

Jeśli nie opracowujemy nowej wersji C #, nie musimy trzymać się wszystkich wytycznych Microsoft. Czasami nie są najlepsze.

Glauber
źródło