Interpolacja ciągów a String.Format

114

Czy istnieje zauważalna różnica w wydajności między używaniem interpolacji ciągów:

myString += $"{x:x2}";

vs String.Format ()?

myString += String.Format("{0:x2}", x);

Pytam tylko dlatego, że Resharper podpowiada poprawkę, a mnie już wcześniej oszukano.

Krythic
źródło
4
Dlaczego nie spróbować obu i zobaczyć, czy zauważysz różnicę?
Blorgbeard wychodzi
57
@Blorgbeard Szczerze, jestem leniwy. I myślę, że zajęłoby to mniej czasu, gdyby któryś z was, porządnych mężczyzn / kobiet znał odpowiedź od ręki.
Krythic
26
Uwielbiam to, jak kiedy po raz pierwszy zadałem to pytanie, zostało odrzucone na zapomnienie, a teraz, dwa lata później, jest do +21.
Krythic
47
Poważnie. Jak można wątpić w przydatność tego pytania? Czy możesz sobie wyobrazić całkowitą stratę roboczogodzin, gdyby każdy zadający to pytanie musiał „spróbować samemu i zobaczyć?”. Nawet jeśli zajęło to tylko 5 minut, pomnóż to przez ponad 10000 programistów, którzy do tej pory widzieli to pytanie. A co wtedy, gdy współpracownik wątpi w Twoje wyniki? Czy to wszystko jeszcze raz? A może po prostu odeślij ich do tego wpisu SO. W pewnym sensie to jest po to.
BTownTKD,
8
@BTownTKD To typowe zachowanie Stackoverflow dla Ciebie. Jeśli ktoś korzysta z witryny zgodnie z jej przeznaczeniem, natychmiast zostaje wyobcowany. Jest to również jeden z powodów, dla których uważam, że powinniśmy mieć możliwość zbiorowego blokowania kont. Wiele osób po prostu nie zasługuje na to, by być na tej stronie.
Krythic

Odpowiedzi:

72

Godne uwagi jest względne. Jednak: interpolacja ciągów jest zmieniana w string.Format()czasie kompilacji, więc powinny zakończyć się tym samym wynikiem.

Istnieją jednak drobne różnice: jak wynika z tego pytania, konkatenacja ciągów znaków w specyfikatorze formatu skutkuje dodatkowym string.Concat()wywołaniem.

Jeroen Vannevel
źródło
4
W rzeczywistości interpolacja ciągów może w niektórych przypadkach skompilować się do konkatenacji ciągów (np. Gdy intjest używane a). var a = "hello"; var b = $"{a} world";kompiluje się do konkatenacji ciągów. var a = "hello"; var b = $"{a} world {1}";kompiluje się do formatu string.
Omar Muscatello
5

interpolacja ciągów jest zamieniana na string.Format () w czasie kompilacji.

Również w string.Format możesz określić kilka wyjść dla pojedynczego argumentu i różne formaty wyjściowe dla pojedynczego argumentu. Ale interpolacja ciągów jest chyba bardziej czytelna. Więc to zależy od Ciebie.

a = string.Format("Due date is {0:M/d/yy} at {0:h:mm}", someComplexObject.someObject.someProperty);

b = $"Due date is {someComplexObject.someObject.someProperty:M/d/yy} at {someComplexObject.someObject.someProperty:h:mm}";

Istnieją wyniki testów wydajności https://koukia.ca/string-interpolation-vs-string-format-string-concat-and-string-builder-performance-benchmarks-c1dad38032a

Paweł
źródło
2
interpolacja ciągów jest po prostu czasami przekształcana w String::Format. a czasami w String::Concat. A test wydajności na tej stronie jest raczej nieistotny: liczba argumentów, które przekazujesz do każdej z tych metod, jest zależna. concat nie zawsze jest najszybszy, a stringbuilder nie zawsze jest najwolniejszy.
Matthias Burger
3

Pytanie dotyczyło wydajności, jednak tytuł mówi tylko „vs”, więc czuję, że muszę dodać jeszcze kilka punktów, chociaż niektóre z nich są uparte.

  • Lokalizacja

    • Nie można zlokalizować interpolacji ciągów ze względu na jej charakter kodu wbudowanego. Przed lokalizacją został zmieniony na string.Format. Jest jednak do tego narzędzia (np ReSharper.).
  • Konserwowalność (moja opinia)

    • string.Formatjest znacznie bardziej czytelny, ponieważ skupia się na zdaniu , które chciałbym wyrazić, na przykład podczas konstruowania ładnego i znaczącego komunikatu o błędzie. Używanie {N}symboli zastępczych zapewnia mi większą elastyczność i łatwiej jest je później zmodyfikować.
    • Ponadto wbudowany specyfikator formatu w wykorzystywaniu jest łatwy do błędnego odczytania i łatwy do usunięcia wraz z wyrażeniem podczas zmiany.
    • Podczas używania złożonych i długich wyrażeń interpolacja szybko staje się jeszcze trudniejsza do odczytania i utrzymania, więc w tym sensie nie skaluje się dobrze, gdy kod ewoluuje i staje się bardziej złożony. string.Formatjest na to znacznie mniej podatny.
    • Ostatecznie chodzi o rozdzielenie obaw: nie lubię mieszać tego, jak to ma wyglądać, z tym, co powinno być przedstawione .

Na tej podstawie postanowiłem więc trzymać się string.Formatwiększości mojego kodu. Jednak przygotowałem metodę rozszerzenia, aby mieć płynniejszy sposób kodowania, który lubię o wiele bardziej. Wdrożenie rozszerzenia jest jednowierszowe i wygląda tak po prostu w użyciu.

var myErrorMessage = "Value must be less than {0:0.00} for field {1}".FormatWith(maximum, fieldName);

Interpolacja to świetna funkcja, nie zrozum mnie źle. Ale IMO świeci najlepiej w tych językach, w których brakuje tej string.Formatpodobnej funkcji, na przykład JavaScript.

Zoltán Tamási
źródło
Dziękuję za dodanie do tego.
Krythic
1
Nie zgodziłbym się na łatwość utrzymania; przyznany ReSharper sprawia, że ​​nieco łatwiej jest dopasować wstawione wartości do odpowiadających im indeksów (i odwrotnie), ale myślę, że nadal jest to większe obciążenie poznawcze, aby dowiedzieć się, czy {3}jest X lub Y, zwłaszcza jeśli zaczniesz zmieniać format. Przykład Madlibs: $"It was a {adjective} day in {month} when I {didSomething}"vs string.Format("It was a {0} day in {1} when I {2}", adjective, month, didSomething)-> $"I {didSomething} on a {adjective} {month} day"vsstring.Format("I {2} on a {0} {1} day", adjective, month, didSomething)
drzaus
@drzaus Dzięki za podzielenie się swoimi przemyśleniami. Masz dobre strony, ale jest to prawdą tylko wtedy, gdy używamy tylko prostych, dobrze nazwanych zmiennych lokalnych. To, co widziałem wiele razy, to złożone wyrażenia, wywołania funkcji, cokolwiek wstawiono do interpolowanego ciągu. Z string.Formatmyślę, że są znacznie mniej podatne na ten temat. Tak czy inaczej, dlatego podkreśliłem, że to moja opinia :)
Zoltán Tamási