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?

Xaisoft
źródło
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.

alc6379
źródło
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.

Mark Byers
źródło
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);
Corbin March
źródło
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 #.

Mohamad Shiralizadeh
źródło
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\\.");
BoltClock
źródło
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.

AndyO
źródło