Jaka jest różnica między zwykłym ciągiem a ciągiem dosłownym?


166

Mam wersję próbną Resharper i zawsze sugeruje, żebym zmienił ciągi zwykłe na ciągi dosłowne. Jaka jest różnica?


3
Nigdy nie widziałem tej sugestii od ReSharper. Czy możesz podać przykład, na którym to sugeruje?
— John Saunders

3
Właśnie to dostałem. Pierwsza sugestia dotyczyła przeniesienia go do zasobu, ale druga polegała na nadaniu mu dosłownego ciągu: MessageBox.Show ("Dziobaka należy pogłaskać, zanim będzie można kontynuować pracę.");
— B. Clay Shannon

Ciągle to rozumiem. Zwykle jest to jedno z ostrzeżeń, które chcesz wyłączyć, ponieważ sugeruje tworzenie ciągów dosłownie bez żadnego powodu.
— Dziekan Świątek

Jeśli podoba Ci się moja sugerowana funkcja dla środowiska Visual Studio IDE, zagłosuj tutaj: developercommunity.visualstudio.com/idea/602807/ ...
— Olivier Jacot-Descombes

Odpowiedzi:


191

Dosłowny ciąg to taki, który nie wymaga zmiany znaczenia, jak nazwa pliku:

string myFileName = "C:\\myfolder\\myfile.txt";

byłoby

string myFileName = @"C:\myfolder\myfile.txt";

Symbol @ oznacza dosłowne odczytywanie tego ciągu i nie interpretuje w inny sposób znaków sterujących.


12
Zastanawiam się, dlaczego Resharper sugeruje tę zmianę. Czy jacyś guru CLR wiedzą, czy ciągi znaków dosłownych są przetwarzane wydajniej, ponieważ znaki ucieczki można zignorować?
— Matt Peterson

9
Myślę, że może ReSharper to sugeruje, ponieważ ciąg dosłowny jest bardziej czytelny.
— andyp

36
Uważam, że jest to rodzaj konwencji kodowania (nigdy wcześniej nie widziałem ani nie słyszałem). W przypadku ciągów znaków ReSharper sugeruje przeniesienie go do pliku zasobów w celu lokalizacji lub uczynienie go dosłownie - w przypadku ciągów dosłownych ReSharper nie oferuje już opcji lokalizacji ciągu. Wygląda więc na konwencję tworzenia wszystkich łańcuchów, które nie wymagają lokalizacji dosłownie.
— Daniel Brückner

Powiedzmy, że mamy przypisany literał łańcuchowy do zmiennej łańcuchowej, string myFileName = "C: \\ myfolder \\ myfile.txt"; Teraz chcę przekonwertować zmienną ciąg myFileName na ciąg dosłowny. Jak mam to zrobić? czy to działa? string verbatimStr = @myFileName;
— sanjeev bhusal

3
@sanjeevbhusal: Tak naprawdę nigdy tego nie robisz. @ "C: \ mojfolder \ mojplik.txt" i "C: \\ mojfolder \\ mojplik.txt" to to samo co CLR. Zasadniczo to tylko cukier syntaktyczny.
— alc6379

68

Jest to omówione w sekcji 2.4.4.5 specyfikacji języka C # :

2.4.4.5 Literały łańcuchowe

C # obsługuje dwie formy literałów ciągów: zwykłe literały ciągów i dosłowne literały ciągów.

Zwykły literał ciągu składa się z zera lub większej liczby znaków ujętych w podwójne cudzysłowy, jak w przypadku „hello”, i może zawierać zarówno proste sekwencje ucieczki (takie jak \ t dla znaku tabulacji), jak i sekwencje szesnastkowe i sekwencje unikowe Unicode.

Dosłowny literał ciągu składa się ze znaku @, po którym następuje znak podwójnego cudzysłowu, zero lub więcej znaków oraz zamykający znak podwójnego cudzysłowu. Prostym przykładem jest @ "hello". W dosłownym literale ciągu znaki między ogranicznikami są interpretowane dosłownie, a jedynym wyjątkiem jest sekwencja ucieczki cudzysłowu. W szczególności proste sekwencje specjalne oraz sekwencje szesnastkowe i unikowe Unicode nie są przetwarzane w dosłownych literałach łańcuchowych. Dosłowny literał ciągu może obejmować wiele wierszy.

Innymi słowy, jedynym znakiem specjalnym w @ „dosłownym literale ciągu” jest znak podwójnego cudzysłowu. Jeśli chcesz napisać ciąg dosłowny zawierający cudzysłów, musisz wpisać dwa cudzysłowy. Wszystkie inne znaki są interpretowane dosłownie.

Możesz nawet mieć dosłowne nowe wiersze w dosłownym literale ciągu. W zwykłym literale łańcuchowym nie można mieć dosłownych nowych linii. Zamiast tego musisz użyć na przykład "\n".

Dosłowne literały ciągów znaków są często przydatne do osadzania nazw plików i wyrażeń regularnych w kodzie źródłowym, ponieważ odwrotne ukośniki w tych typach ciągów są powszechne i trzeba je było zmienić, jeśli został użyty zwykły literał ciągu.

W czasie wykonywania nie ma różnicy między ciągami utworzonymi ze zwykłych literałów ciągów a ciągami utworzonymi z dosłownych literałów ciągów - oba są typu System.String.


27

Nie ma różnicy w czasie wykonywania między ciągiem a ciągiem dosłownym. Różnią się tylko w czasie kompilacji. Kompilator akceptuje mniej sekwencji ucieczki w ciągu dosłownym, więc to, co widzisz, jest tym, co otrzymujesz, inne niż cytat.

Możesz również użyć znaku dosłownie @, aby nakazać kompilatorowi traktowanie słowa kluczowego jako nazwy:

var @if = "if";
//okay, treated as a name
Console.WriteLine(@if);
//compiler err, if without @ is a keyword
Console.WriteLine(if);

var @a = "a";
//okay
Console.WriteLine(@a);
//also okay, @ isn't part of the name
Console.WriteLine(a);

16

Możesz również mieć ciąg wielowierszowy, używając ciągów dosłownych:

Console.WriteLine(@"This
    is
    a
    Test
    for stackoverflow");

bez @ciebie pojawił się błąd.

W VB14 jest nowa funkcja o nazwie Multiline Strings, jest jak ciągi dosłowne w C #.

Ciągi wielowierszowe

Wskazówka dla profesjonalistów: literały ciągów VB są teraz dokładnie takie same jak ciągi dosłowne w języku C #.


13

Zwykłe ciągi używają specjalnych sekwencji ucieczki do tłumaczenia na znaki specjalne.

/*
This string contains a newline
and a tab    and an escaped backslash\
*/
Console.WriteLine("This string contains a newline\nand a tab\tand an escaped backslash\\");

Dosłowne ciągi znaków są interpretowane tak, jak są, bez tłumaczenia żadnych sekwencji ucieczki:

/* 
This string displays as is. No newlines\n, tabs\t or backslash-escapes\\.
*/
Console.WriteLine(@"This string displays as is. No newlines\n, tabs\t or backslash-escapes\\.");

0

Jeśli chcesz usunąć ostrzeżenia Resharper, możesz użyć:

Localizable(false)

W przypadku parametrów, lokalizacji plików, np. to mogłoby być dobre rozwiązanie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.