Co to jest @ przed ciągiem w C #?


602

To jest pytanie .NET dla C # (lub ewentualnie VB.net), ale próbuję dowiedzieć się, jaka jest różnica między następującymi deklaracjami:

string hello = "hello";

vs.

string hello_alias = @"hello";

Wydruk na konsoli nie ma znaczenia, właściwości długości są takie same.


Proszę zobaczyć (i upvote) moja propozycja dla Visual Studio IDE dla lepszego formatowania tekstu verbatim: wcięcie multi-linię dosłowne ciągi .
Olivier Jacot-Descombes

Dla jasności powyższe przykłady dają dokładnie taki sam wynik z lub bez @.
Miro J.,

Odpowiedzi:


767

Oznacza ciąg jako dosłowny dosłowny ciąg - wszystko w ciągu, które normalnie byłoby interpretowane jako sekwencja ucieczki, jest ignorowane.

Więc "C:\\Users\\Rich"to samo co@"C:\Users\Rich"

Jest jeden wyjątek: sekwencja ucieczki jest potrzebna dla podwójnego cudzysłowu. Aby uniknąć podwójnego cudzysłowu, musisz umieścić dwa podwójne cudzysłowy w rzędzie. Na przykład @""""ocenia na ".


1
@RichardEverett Zrozumiałem odpowiedź, ale mam wątpliwości, jakie jest faktyczne wykorzystanie tej funkcji?
Arun

24
@Arun Jest to bardzo przydatne, gdy mamy do czynienia z ciągami znaków, takimi jak definicje wyrażeń regularnych, które często wymagają ucieczki
James Thorpe

25
+ treść
wielowierszowa

4
nadal będziesz musiał podwajać nawiasy klamrowe, {{jeśli chcesz używać zwykłego nawiasu klamrowego w string.Formatrozmowie.
Dave Cousineau,

4
@RichardEverett jest bardzo przydatny do tworzenia literałów wieloliniowych bez konieczności dzielenia linii na części.
John Mott,

256

Jest to dosłowny ciąg dosłowny . Oznacza to, że ucieczka nie jest stosowana. Na przykład:

string verbatim = @"foo\bar";
string regular = "foo\\bar";

Tutaj verbatimi regularmają tę samą zawartość.

Umożliwia także zawartość wieloliniową - co może być bardzo przydatne w SQL:

string select = @"
SELECT Foo
FROM Bar
WHERE Name='Baz'";

Jedynym elementem ucieczki, który jest niezbędny do dosłownych literałów łańcuchowych, jest uzyskanie podwójnego cudzysłowu („), który robisz, podwajając go:

string verbatim = @"He said, ""Would you like some coffee?"" and left.";
string regular = "He said, \"Would you like some coffee?\" and left.";

16
Pozwala także na używanie słów zastrzeżonych jako nazw zmiennych i innych rzeczy. Jak public int GetValueOrDefault (int @default);
Svish

5
Svish: Prawda, ale nie związana z tym konkretnym pytaniem.
Jon Skeet

63

„@” Ma również inne znaczenie: umieszczenie go przed deklaracją zmiennej pozwala na użycie zastrzeżonych słów kluczowych jako nazw zmiennych.

Na przykład:

string @class = "something";
int @object = 1;

Znalazłem tylko jedno lub dwa uzasadnione zastosowania do tego. Głównie w ASP.NET MVC, jeśli chcesz zrobić coś takiego:

<%= Html.ActionLink("Text", "Action", "Controller", null, new { @class = "some_css_class" })%>

Który tworzyłby link HTML taki jak:

<a href="/Controller/Action" class="some_css_class">Text</a>

W przeciwnym razie trzeba użyć „Klasy”, która nie jest zastrzeżonym słowem kluczowym, ale wielkie litery „C” nie spełniają standardów HTML i po prostu nie wyglądają dobrze.


18

Ponieważ wyraźnie poprosiłeś również o VB, dodam tylko, że ta pełna składnia łańcuchowa nie istnieje w VB, tylko w C #. Przeciwnie, wszystkie ciągi są dosłownie w VB (z wyjątkiem faktu, że nie mogą one zawierać podziały wiersza, w przeciwieństwie do C # verbatim strings):

Dim path = "C:\My\Path"
Dim message = "She said, ""Hello, beautiful world."""

Sekwencje specjalne nie istnieją w VB (z wyjątkiem podwojenia znaku cudzysłowu, jak w ciągach C #), co czyni kilka rzeczy bardziej skomplikowanymi. Na przykład, aby napisać następujący kod w VB, musisz użyć konkatenacji (lub dowolnego innego sposobu skonstruowania łańcucha)

string x = "Foo\nbar";

W VB byłoby to napisane w następujący sposób:

Dim x = "Foo" & Environment.NewLine & "bar"

( &jest operatorem konkatenacji ciągów VB. +Równie dobrze można użyć.)


1
Ojej, to brzmi denerwująco ... jeszcze bardziej cieszę się, że teraz używam C #: p
Svish

Nie można osadzać podziałów wierszy w literałach ciągów VB, nawet jeśli można dosłownie literały ciągów w języku C #. Nie są więc tacy sami.
Joey

@Svish, Czekaj, czy coś mi umknęło? To wcale nie jest oszustwo dla VB. Rzeczywiście jest to jedno miejsce, w którym VB wygrywa C #. Lepiej to zrobić w ten sposób i jawnie powiązać znaki nowej linii i znaki specjalne, zamiast rzucać wszystkie znaki specjalne między "i ".
Pacerier,

@Pacerier To nonsens. Gdy tylko zrobisz coś więcej niż tylko trywialne przetwarzanie łańcucha, niezbędne są odpowiednie narzędzia do budowania łańcucha, a wśród nich przede wszystkim umiejętność zwięzłego posługiwania się znakami specjalnymi. Jednak zarówno C #, jak i VB mają String.Format, co pozwala to zrobić. W rzeczywistości nigdy nie pisałbym "x" & Environment.NewLine, a zamiast tego zawsze używałem String.Format("x{0}", Environment.Newline)itd. Mimo to C # jest tutaj wygodniejszy.
Konrad Rudolph

@KonradRudolph, wybrałbym "x" & nl & nllub "x" + nl + nllub "x" . $nl . $nldowolny dzień nad "x\n\n". Też "x" + bs + bs skończone "x\\\\". I "x" + q + qponad "x\"\""/ "x""""". Jeśli chodzi o to String.Format, to kolejny problem niezwiązany z powyższym porównaniem.
Pacerier,

10

http://msdn.microsoft.com/en-us/library/aa691090.aspx

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

Zwykły literał ciąg składa się z zerowej lub większej liczby znaków zawartych w podwójnych cudzysłowach, jak w „hello”, i może zawierać zarówno proste sekwencje specjalne (takie jak \ t dla znaku tabulacji), jak i sekwencje specjalne szesnastkowe i Unicode.

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


9

Jest to dosłowny ciąg znaków, który zmienia reguły zmiany znaczenia - jedynym znakiem, który jest teraz zmieniany, jest „, znak zmiany znaczenia na„ ”. Jest to szczególnie przydatne w przypadku ścieżek plików i wyrażeń regularnych:

var path = @"c:\some\location";
var tsql = @"SELECT *
            FROM FOO
            WHERE Bar = 1";
var escaped = @"a "" b";

itp


Nie brakuje Ci @ w twoim przykładzie, Marc? Czy jest to ustawienie domyślne, gdy używam var? Trochę zdezorientowany ...
Dirk Vollmar

1
OK - to naprawdę bardzo dziwne. Zastanawiam się, czy redaktor je zgryzł?
Marc Gravell

9

Skopiowano z MSDN :

W czasie kompilacji ciągi dosłowne są konwertowane na zwykłe ciągi ze wszystkimi tymi samymi sekwencjami ucieczki. Dlatego jeśli wyświetlisz pełny ciąg w oknie obserwacyjnym debuggera, zobaczysz znaki specjalne dodane przez kompilator, a nie pełną wersję z kodu źródłowego. Na przykład pełny ciąg @"C:\files.txt"pojawi się w oknie zegarka jako "C:\\files.txt".


Który jest typowym wprowadzającym w błąd fragmentem dokumentacji Microsoft, IMHO! To, co powyższe stwierdza jako wynik końcowy, jest prawidłowe, ale podstawową prawdą jest to, że ciągi w C # są konwertowane na odpowiednią sekwencję bajtów (lub wielobajtowe kody znaków). C # pozwala na dwa różne sposoby reprezentowania leżącego u podstaw łańcucha: @ „...” lub „...”. Debuger zawsze wybiera sposób „...” i nie jest w stanie stwierdzić, który został użyty. (Sekwencje specjalne, takie jak \ n lub „”, dotyczą tylko programowania i reprezentacji ciągów na poziomie wyświetlania i nigdy nie są zapisywane w ciągach podstawowych!)
MikeBeaton,

8

Stawianie @ znaku przed ciągiem umożliwia użycie znaków specjalnych, takich jak odwrotny ukośnik lub cudzysłowy, bez konieczności używania specjalnych kodów lub znaków specjalnych.

Możesz więc napisać:

string path = @"C:\My path\";

zamiast:

string path = "C:\\My path\\";

3

Wyjaśnienie jest proste. Aby przedstawić ciąg "string\", kompilator potrzebuje, "string\\"ponieważ \jest to znak zmiany znaczenia. Jeśli użyjesz @"string\"zamiast tego, możesz zapomnieć o \\.

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.