Pytanie Jaka jest różnica między ciągiem i ciąg w C #?


Przykład (zanotuj sprawę):

string s = "Hello world!";
String s = "Hello world!";

Jakie są wytyczne do wykorzystania każdego? A jakie są różnice?


5362


pochodzenie


@ O.R.Mapper, ale pozostaje faktem string jest leksykalny konstrukcja C # gramatyka natomiast System.String jest tylko typem. Niezależnie od jakichkolwiek wyraźny Różnica wspomniana w każdej specyfikacji, wciąż istnieje ta niejawna różnica, którą można by zasto- sować z pewną niejednoznacznością. Sam język musi wsparcie string w taki sposób, że implementacja nie jest (całkiem) zobowiązana do rozważenia dla konkretnej klasy w BCL. - Kirk Woll
@KirkWoll: zgodnie ze specyfikacją języka, sam język musi rozważać string być dokładnie taki sam jak typ BCL System.String, nic więcej. To wcale nie jest niejednoznaczne. Oczywiście, możesz zaimplementować swój własny kompilator, używając gramatyki C # i użyć wszystkich znalezionych tokenów dla czegoś arbitralnego, niezwiązanego z tym, co jest zdefiniowane w specyfikacji języka C #. Jednak wynikowy język będzie wyglądał tylko jak C #, nie można go uznać za C #. - O. R. Mapper
Możesz użyć string bez użycia dyrektywy dla systemu. Nie możesz tego zrobić z String. - Wilsu
Dla kogoś, kto pochodzi z Algola i Fortrana, ta dyskusja pokazuje, że coś jest nie w porządku string. Konieczne jest skrócenie System.String, ale jako pseudonim wydaje się całkiem podobny, ale nie jest dokładnie taki sam. Jednak po kilku latach C # mogę bezpiecznie używać string i string.Format() i nie martw się System.String. - Roland
Gdyby tego rodzaju pytanie zadano w 2017 r., Otrzymywałby on 4 000 zniżek, 2000 linków do strony klasy MSDN String i został zamknięty jako mało wydajny. - IRGeekSauce


Odpowiedzi:


string to alias w C # dla System.String.
Technicznie nie ma różnicy. To jest jak int  vs.  System.Int32.

Jeśli chodzi o wytyczne, ogólnie zaleca się stosowanie string za każdym razem, gdy odnosisz się do obiektu.

na przykład

string place = "world";

Podobnie, myślę, że ogólnie zaleca się używać String jeśli chcesz odnieść się do klasy.

na przykład

string greet = String.Format("Hello {0}!", place);

Jest to styl, z którego korzysta Microsoft ich przykłady.

Wygląda na to, że wskazówki w tym obszarze mogły ulec zmianie, ponieważ StyleCop teraz wymusza użycie aliasów specyficznych dla C #.


5097



Jeśli zdecydujesz się na użycie StyleCop i będziesz go używał, będzie to oznaczało używanie typów właściwych dla danego języka. Więc dla C # będziesz mieć ciąg (zamiast String), int (zamiast Int32), float (zamiast Single) - stylecop.soyuz5.com/SA1121.html - Dominic Zukiewicz
Zawsze używam aliasów, ponieważ założyłem, że pewnego dnia może się to przydać, ponieważ działają one jako abstrakcja, dlatego też mogą zostać zmienione ich implementacje bez mojej wiedzy. - Rob
Visual Studio 2015 mówi, że String.Format powinien zostać zmieniony na string.Format, więc myślę, że Microsoft idzie w ten sposób. Zawsze stosowałem również String dla metod statycznych. - Sami Kuhmonen
Jak już przeczytałem, zauważyłem, że kilka komentarzy jest po prostu niepoprawnych. @ DRAirey1 Z czasem okaże się, że stary sposób nadal jest najlepszy, jeśli wątpisz, to wtedy ośmielam się spróbować napisać kod C # bez użycia Visual Studio. Jest to praktycznie niemożliwe i sytuacja, która pojawia się od czasu do czasu w pracach nad tworzeniem stron internetowych. @ Vlad Nie musisz importować niczego, aby użyć String. @Abhi Twój komentarz jest bezcelowy i równie prawdziwy string.Format(). @KlitosG Nie, to nieprawda. Wszystkie działają dokładnie tak samo. - krowe2
Czy mógłbyś dodać uwagę, że tak naprawdę istnieje różnica? Na przykład: nameof(string) nie skompiluje się, podczas gdy nameof(String) będzie. - Jeroen Vannevel


Tylko ze względu na kompletność, oto zrzut mózgu powiązanych informacji ...

Jak zauważyli inni, string to alias dla System.String. Kompilują się do tego samego kodu, więc w czasie wykonywania nie ma żadnej różnicy. To tylko jeden z aliasów w języku C #. Pełna lista to:

object:  System.Object
string:  System.String
bool:    System.Boolean
byte:    System.Byte
sbyte:   System.SByte
short:   System.Int16
ushort:  System.UInt16
int:     System.Int32
uint:    System.UInt32
long:    System.Int64
ulong:   System.UInt64
float:   System.Single
double:  System.Double
decimal: System.Decimal
char:    System.Char

Oprócz string i objectwszystkie aliasy mają być typami wartości. decimal jest typem wartości, ale nie typem pierwotnym w CLR. Jedynym typem pierwotnym, który nie ma aliasu, jest System.IntPtr.

W specyfikacji, aliasy typu wartości znane są jako "typy proste". Literały mogą być używane dla stałych wartości każdego prostego typu; żadne inne typy wartości nie mają form literowych. (Porównaj to z VB, który pozwala DateTime literały i ma na to alias.)

Jest jedna okoliczność, w której ty mieć używać aliasów: jawnie określając podstawowy typ enum. Na przykład:

public enum Foo : UInt32 {} // Invalid
public enum Bar : uint   {} // Valid

To tylko kwestia sposobu, w jaki specyfik definiuje deklaracje enum - część po dwukropku musi być typ całkowy produkcja, która jest jednym z tokenów sbyte, byte, short, ushort, int, uint, long, ulong, char... w przeciwieństwie do a rodzaj produkcja używana na przykład w deklaracjach zmiennych. Nie wskazuje żadnej innej różnicy.

Wreszcie, gdy chodzi o to, do czego należy użyć: osobiście wszędzie używam aliasów do implementacji, ale typu CLR dla dowolnych interfejsów API. To naprawdę nie ma znaczenia, którego używasz pod względem implementacji - spójność wśród twojego zespołu jest przyjemna, ale nikt się tym nie przejmuje. Z drugiej strony, naprawdę ważne jest, że jeśli odnosisz się do typu w API, robisz to w sposób neutralny językowo. Metoda nazwana ReadInt32 jest jednoznaczny, natomiast metoda zwana ReadInt wymaga interpretacji. Dzwoniący może używać języka, który definiuje int alias dla Int16, na przykład. Projektanci środowiska .NET podążają tą ścieżką, czego dobrym przykładem jest BitConverter, BinaryReader i Convert klasy.


3037



Sytuacja dotycząca dziedziczenia z wyliczeniem jest interesująca. Czy możesz wskazać w dokumentacji, dlaczego do wyliczania należy używać aliasu? A może to znany błąd? - JaredPar
Znajduje się w sekcji 14.1 specyfikacji (nie mogę tu łatwo przytoczyć, ponieważ jest zbyt długa). Nie mówi wprost, że musisz użyć tego aliasu, ale aliasy są raczej traktowani jak ich własne typy. To wszystko trochę dziwne. - Jon Skeet
@PiPeep, co jest bardziej zdumiewające niż duża liczba upvotes, to oszałamiająca niewielka ilość downvotes (uważaj, że 5 najwyższych stanowisk ma w sumie ponad 2000 przegranych, a mimo to tylko 1 przegrywają wśród nich wszystkich). Zwłaszcza jeśli bierzesz pod uwagę, że w każdej społeczności zawsze są "nienawidzący", naprawdę to jest po prostu niewiarygodne. - corsiKa
Jedna interesująca różnica między string i String czy to string' is a keyword in c#, so you can not use it as a variable name.For Ex: string string = "hi";//compiler error, but String String = "hi"; `jest dopuszczalne, jako String jest identyfikatorem, a nie słowem kluczowym. - Sanjeev Rai
@SanjeevRai: Tak. Możesz użyć @string aby utworzyć identyfikator, który kończy się jako string chociaż. To rodzaj mechanizmu ucieczki. - Jon Skeet


String oznacza System.String i jest typem .NET Framework. string to alias w języku C # dla System.String. Oba są skompilowane do System.String w IL(Język średniozaawansowany), więc nie ma różnicy. Wybierz to, co lubisz i użyj tego. Jeśli kodujesz w C #, wolałbym string ponieważ jest to alias typu C # i dobrze znany programistom C #.

Mogę powiedzieć to samo (int, System.Int32) itp..


608



`Jeśli kodujesz w C #, wolałbym ciąg jako alias typu C # i dobrze znany przez programistów C #, kiedy osoba z C # nie znałaby architektury .NET. +1, bo myślę, że ogólnie jest to najlepsza odpowiedź, ale punkt, o którym wspomniałem, wydaje się dziwny. - MyDaftQuestions
Osobiście wolę używać "Int32", ponieważ natychmiast pokazuje zakres wartości. Wyobraź sobie, że uaktualnili typ "int" na późniejszych systemach bitowych. "int" w c jest najwyraźniej postrzegane jako "typ całkowity, z którym procesor docelowy najskuteczniej pracuje z"i zdefiniowane jako "co najmniej 16 bitów". Wolę przewidywalną konsekwencję, dziękuję bardzo. - Nyerguds
@MyDaftQuestions Zgadzam się. Jeśli cokolwiek, miałoby to sens konsekwentnie używać typów .net ponieważ są językami nieświadomymi, a typ jest oczywisty, niezależny od jakiegokolwiek języka (czy znam wszystkie cechy F # i VB?). - Peter A. Schneider


Najlepsza odpowiedź, jaką kiedykolwiek słyszałem na temat korzystania z podanych aliasów typów w języku C #, pochodzi od Jeffreya Richtera z jego książki CLR Via C #. Oto jego 3 powody:

  • Widziałem wielu programistów zdezorientowanych, nie wiedzących, czy ich użyć strunowy lub Strunowy w ich kodzie. Ponieważ w C # łańcuch (słowo kluczowe) dokładnie odwzorowuje System.String (typ FCL), nie ma różnicy i można z nich korzystać.
  • W języku C # długie mapy do System.Int64, ale w innym języku programowania, długie może mapować na Int16 lub Int32. W rzeczywistości C ++ / CLI faktycznie traktuje długo jak Int32. Ktoś, kto czyta kod źródłowy w jednym języku, może łatwo zinterpretować intencję kodu, jeśli był przyzwyczajony do programowania w innym języku programowania. W rzeczywistości większość języków nie będzie nawet leczyć długie jako słowo kluczowe i nie skompiluje kodu, który z niego korzysta.
  • FCL ma wiele metod, które mają nazwy typów jako część ich nazw metod. Na przykład BinaryReader type oferuje metody takie jak ReadBoolean, ReadInt32, ReadSinglei tak dalej, i System.Convert type oferuje metody takie jak ToBoolean, ToInt32, ToSingle, i tak dalej. Chociaż napisanie poniższego kodu jest legalne, linia z floatem jest dla mnie bardzo nienaturalna i nie jest oczywiste, że linia jest poprawna:
BinaryReader br = new BinaryReader(...);
float val  = br.ReadSingle(); // OK, but feels unnatural
Single val = br.ReadSingle(); // OK and feels good

Więc masz to. Myślę, że to są naprawdę dobre punkty. Jednak nie uważam się za stosującego radę Jeffreya w moim własnym kodzie. Być może jestem zbyt utknął w moim świecie C #, ale w końcu próbuję sprawić, by mój kod wyglądał jak kod ramowy.


411



Drugi punkt brzmi właściwie jak powód nie używać string, int itp. - MauganRa
@MauganRa A powinno, autor książki wymienia te powody, dlaczego on nie używa aliasy. - tomi.lee.jones
"Jeśli ktoś czyta kod źródłowy C #, powinien interpretować długo zgodnie ze specyfikacją językową, a nie inną specyfikacją językową." To całkowicie mija się z celem. To nie tak, że nikt zamierza Aby źle zinterpretować kod, po prostu łatwo jest dojść do niewłaściwego wniosku, gdy typ ma inne znaczenie niż to, co programista widzi codziennie w innym kontekście. Wszyscy popełniamy błędy; używanie typów o wyraźnie określonych nazwach powoduje, że te błędy są mniej prawdopodobne. - Darryl
+ Te powody podsumowują moje odczucia w tej sprawie. Kiedy po raz pierwszy zacząłem kodowanie w C # (pochodzące z Java / C ++ / C w tle) myślałem, że aliasy były brzydkie. Wciąż tak się czuję, niestety większość świata nie wydaje się ze mną zgodzić, albo nie obchodzi ich, więc używaj małych liter. - gusgorman
@jinzai pytanie dotyczy języka C #, w którym long jest zdefiniowany jako 64-bitowa liczba całkowita ze znakiem, niezależnie od platformy lub kompilatora. A więc w niektórych przypadkach przynajmniej tak robi zależy od języka. - phoog


string jest zastrzeżonym słowem, ale String to tylko nazwa klasy. To znaczy że string nie może być użyte jako nazwa zmiennej samodzielnie.

Jeśli z jakiegoś powodu chciałeś zmienną zwaną strunowyzobaczysz tylko pierwszą z tych kompilacji:

StringBuilder String = new StringBuilder();  // compiles
StringBuilder string = new StringBuilder();  // doesn't compile 

Jeśli naprawdę chcesz wywołać nazwę zmiennej strunowy możesz użyć @ jako przedrostek:

StringBuilder @string = new StringBuilder();

Kolejna krytyczna różnica: Stack Overflow wyróżnia je inaczej.


380



Pamiętaj, że dzwonisz do lokalnego @string jest raczej bezcelowe, ponieważ nazwiska mieszkańców są obecne tylko w PDB. Równie dobrze można to nazwać _string lub coś. Ma więcej sensu dla rzeczy, które mają nazwy dostępne poprzez odbicie, gdzie nazwa @string członek byłby "string". - Roman Starkov
Pamiętaj również, że użycie zastrzeżonego słowa jako nazwy zmiennej jest rażąco nieeleganckie. - Elton
"przepełnienie stosu podświetla je inaczej". Nigdy więcej powodów nie potrzeba :) - Ole Albers
OP nie chce używać łańcucha ani łańcucha jako nazwy zmiennej. Poprosili o wyjaśnienie różnicy między nimi Rodzaje. Twoja odpowiedź służy tylko dodaniu IMO więcej zamieszania - Matt Wilko


Jest jedna różnica - nie możesz użyć String bez using System; uprzednio.


327



domyślnie większość ludzi dodaje to w dowolny sposób na górze pliku. VS robi to domyślnie w większości przypadków nie wszystkich! - IbrarMumtaz
Domyślnie dodaję tylko using Oświadczenia, których wymagam, i wyraźnie usuwam wszystko, czego nie chcę. Narzędzia zwiększające wydajność> "[x] Usuń i formatuj dane dotyczące zapisywania" - JMD
@JMD Zmodyfikowałem plik szablonu .cs, aby nie zawierał on żadnych instrukcji u góry! Zmieniłem również szablon klasy na internal sealed. - ErikE


Zostało to omówione powyżej; jednak nie możesz użyć string w odbiciu; musisz użyć String.


269





System.String jest klasą ciągów .NET - w języku C # string to alias dla System.String - więc w użyciu są takie same.

Jeśli chodzi o wytyczne, nie byłbym zbyt przytłoczony i po prostu skorzystam z tego, na co masz ochotę - są ważniejsze rzeczy w życiu, a kod i tak będzie taki sam.

Jeśli znajdziesz systemy budujące, w których konieczne jest określenie rozmiaru liczb całkowitych, których używasz, a więc mają tendencję do korzystania Int16, Int32, UInt16, UInt32 itp., może to wyglądać bardziej naturalnie w użyciu String- i podczas poruszania się między różnymi językami .net może to uczynić rzeczy bardziej zrozumiałymi - w przeciwnym razie użyłbym napisu i int.


204



+1 za stwierdzenie, że są ważniejsze rzeczy w życiu, czuję, że jest to kolejny milionowy komunikat StackOverflow na temat trywialny ma miejsce: en.wikipedia.org/wiki/Parkinson's_law_of_triviality - Sebastian
Po prostu wybierz jedną i bądź konsekwentny. Jeśli pracujesz gdzieś w stylu domu, użyj tego. - Alan B
niestety styl jest osobistym upodobaniem i może być zbyt kosztowny, aby wymusić w dużej bazie kodu w kilku zespołach bez dedykowanego właściciela kodu. zawsze są ważniejsze sprawy, niż dbanie o ciąg w porównaniu z ciągiem. co przywraca nas do "ważniejszych rzeczy w życiu" - aiodintsov


Wolę wielką literę .NET typy (a nie aliasy) z powodów formatowania. The .NET typy są takie same jak inne typy obiektów (w końcu typy wartości są właściwymi obiektami).

Słowa warunkowe i kontrolne (np if, switch, i return) są małe i ciemnoniebieskie (domyślnie). I wolałbym nie mieć niezgody w użyciu i formacie.

Rozważać:

String someString; 
string anotherString; 

167



Czy piszesz również kod typu: Int32 i = 1; Zamiast int i = 1; ? Wydaje się niespójne, aby nie używać aliasu ciągu, gdy jest dostępny. - bytedev
@nashwan: właściwie, tak, używam Int32 i=1; intstead of int i = 1;  Uważam, że ten pierwszy jest bardziej czytelny co do mojego zamiaru: mianowicie, że chcę 32-bitową liczbę całkowitą ze znakiem. - NotMe
Cóż, myślę, że to wszystko zależy od tego, czy deweloper myśli, że piszą kod C # (ciąg) lub .NET code (String). Osobiście przede wszystkim myślę, że piszę C # (i to C #, który używa .NET). - bytedev
@Alex: Chodzi mi o to, że wolę być bardzo konkretny w moim kodowaniu, aby usunąć niejednoznaczność. - NotMe
Na absolutnym drugim końcu spektrum prawie zawsze używam var - tic