Moja aplikacja odczytuje plik Excela za pomocą VSTO i dodaje odczytane dane do pliku StringDictionary
. Dodaje tylko dane, które są liczbami z kilkoma cyframi (1000 1000,2 1000,34 - przecinek jest separatorem w rosyjskich standardach).
Co lepiej sprawdzić, czy bieżący ciąg jest odpowiednią liczbą?
object data, string key; // data had read
try
{
Convert.ToDouble(regionData, CultureInfo.CurrentCulture);
dic.Add(key, regionData.ToString());
}
catch (InvalidCastException)
{
// is not a number
}
lub
double d;
string str = data.ToString();
if (Double.TryParse(str, out d)) // if done, then is a number
{
dic.Add(key, str);
}
Muszę używać StringDictionary
zamiast z Dictionary<string, double>
powodu następujących problemów z algorytmem analizowania.
Moje pytania: Która droga jest szybsza? Który jest bezpieczniejszy?
A czy lepiej zadzwonić Convert.ToDouble(object)
czy Convert.ToDouble(string)
?
Odpowiedzi:
Zrobiłem szybki nienaukowy test w trybie wydania. Użyłem dwóch danych wejściowych: „2.34523” i „badinput” w obu metodach i wykonałem iterację 1 000 000 razy.
Prawidłowe dane wejściowe:
Double.TryParse = 646ms Convert.ToDouble = 662 ms
Niewiele się różniło, zgodnie z oczekiwaniami. Dla wszystkich zamiarów i celów są one takie same.
Nieprawidłowe dane wejściowe:
Double.TryParse = 612ms Convert.ToDouble = ..
No cóż ... długo to działało. Całość przeprowadziłem ponownie, używając 1000 iteracji i
Convert.ToDouble
przy złych danych wejściowych zajęło to 8,3 sekundy. Uśrednianie zajmie ponad 2 godziny. Nie obchodzi mnie, jak podstawowy jest test, w przypadku nieprawidłowych danych wejściowychConvert.ToDouble
zgłoszenie wyjątku zrujnuje wydajność.Oto kolejny głos za
TryParse
z pewnymi liczbami, aby to potwierdzić .źródło
Na początek użyłbym
double.Parse
raczej niżConvert.ToDouble
w pierwszej kolejności.Co do tego, czy powinieneś użyć,
Parse
czyTryParse
: czy możesz kontynuować, jeśli są złe dane wejściowe, czy też jest to naprawdę wyjątkowy stan? Jeśli jest wyjątkowy, użyjParse
i pozwól mu wybuchnąć, jeśli wejście jest złe. Jeśli jest to oczekiwane i można je czysto obchodzić, użyjTryParse
.źródło
Wytyczne projektowe .NET Framework zalecają użycie metod Try. Unikanie wyjątków jest zwykle dobrym pomysłem.
Convert.ToDouble(object)
zrobi((IConvertible) object).ToDouble(null);
Który zadzwoni
Convert.ToDouble(string, null)
Więc szybciej jest wywołać wersję string.
Jednak wersja string robi to:
if (value == null) { return 0.0; } return double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
Więc szybciej jest zrobić to
double.Parse
bezpośrednio.źródło
Jeśli nie zamierzasz obsługiwać wyjątku, przejdź do TryParse. TryParse jest szybszy, ponieważ nie musi zajmować się całym śladem stosu wyjątków.
źródło
Generalnie staram się unikać tej
Convert
klasy (co oznacza: nie używam jej), ponieważ uważam ją za bardzo zagmatwaną: kod daje zbyt mało wskazówek na temat tego, co dokładnie się tutaj dzieje, ponieważConvert
pozwala na wiele semantycznie bardzo różnych konwersji z tym samym kodem . Utrudnia to programiście kontrolowanie tego, co dokładnie się dzieje.Dlatego radzę nigdy nie używać tej klasy. Nie jest to również konieczne (z wyjątkiem formatowania binarnego liczby, ponieważ normalna
ToString
metoda klas liczbowych nie oferuje odpowiedniej metody do tego).źródło
Jeśli nie masz 100% pewności co do swoich danych wejściowych, co rzadko się zdarza, powinieneś użyć Double.TryParse.
Convert.ToDouble will throw an exception on non-numbers Double.Parse will throw an exception on non-numbers or null Double.TryParse will return false or 0 on any of the above without generating an exception.
Szybkość analizy staje się drugorzędna, gdy zgłosisz wyjątek, ponieważ nie jest dużo wolniejszy niż wyjątek.
źródło
Dużo nienawiści do klasy Convert tutaj ... Żeby trochę zrównoważyć, jest jedna zaleta Convert - jeśli dostaniesz przedmiot,
może po prostu łatwo zwrócić wartość, jeśli o jest już Double (lub int lub cokolwiek łatwo rzutowalnego).
Używanie Double.Parse lub Double.TryParse jest świetne, jeśli masz już to w ciągu, ale
musi najpierw sprawić, że łańcuch zostanie przeanalizowany i w zależności od danych wejściowych może to być droższe.
źródło
Convert.ToSomething()
jest o wiele bardziej kosztowny niż Parse / TryParse, szczególnie w kontekście iteracjiDouble.TryParse IMO.
Łatwiej Ci sobie poradzić, będziesz dokładnie wiedzieć, gdzie wystąpił błąd.
Następnie możesz sobie z nim poradzić, jak uważasz za stosowne, jeśli zwróci fałsz (tj. Nie może przekonwertować).
źródło
Zawsze wolałem używać tych
TryParse()
metod, ponieważ odwdzięczą się one sukcesem lub niepowodzeniem konwersji bez martwienia się o wyjątki.źródło
To interesujące stare pytanie. Dodam odpowiedź, ponieważ w pierwotnym pytaniu nikt nie zauważył kilku rzeczy.
Co jest szybsze: Convert.ToDouble czy Double.TryParse? Co jest bezpieczniejsze: Convert.ToDouble czy Double.TryParse?
Odpowiem szczegółowo na oba te pytania (zaktualizuję odpowiedź później), ale najpierw:
Ze względów bezpieczeństwa rzecz, której każdy programista przegapił w tym pytaniu, to wiersz (moje wyróżnienie):
Następnie poniższy przykład kodu:
Co ciekawe, jeśli arkusze kalkulacyjne są w rosyjskim formacie liczbowym, ale program Excel nie wpisał poprawnie pól komórek, jaka jest prawidłowa interpretacja wartości pochodzących z programu Excel?
Oto kolejna interesująca rzecz dotycząca tych dwóch przykładów, dotycząca szybkości:
catch (InvalidCastException) { // is not a number }
To prawdopodobnie wygeneruje MSIL, który wygląda tak:
catch [mscorlib]System.InvalidCastException { IL_0023: stloc.0 IL_0024: nop IL_0025: ldloc.0 IL_0026: nop IL_002b: nop IL_002c: nop IL_002d: leave.s IL_002f } // end handler IL_002f: nop IL_0030: return
W tym sensie prawdopodobnie możemy porównać całkowitą liczbę instrukcji MSIL wykonanych przez każdy program - więcej o tym później, gdy zaktualizuję ten post.
Uważam, że kod powinien być poprawny, przejrzysty i szybki ... W takiej kolejności!
źródło
Osobiście uważam, że
TryParse
metoda jest łatwiejsza do odczytania, a która z nich faktycznie zechcesz użyć, zależy od twojego przypadku użycia: jeśli błędy mogą być obsługiwane lokalnie, spodziewasz się błędów i wartości bool odTryParse
jest dobra, w przeciwnym razie możesz po prostu pozwolić wyjątki latają.Spodziewałbym się, że
TryParse
również będzie szybszy, ponieważ pozwala uniknąć narzutu związanego z obsługą wyjątków. Ale użyj narzędzia testowego, takiego jak MiniBench Jona Skeeta, aby porównać różne możliwości.źródło