Jak wstawić znak nowej linii do literału ciągu?

155

W .NET mogę podać oba literały \rlub \nciągi znaków, ale jest sposób na wstawienie czegoś takiego jak znak specjalny „nowy wiersz”, na przykład Environment.NewLinewłaściwość statyczna?

Kapitan Komiks
źródło
9
Jakie jest pytanie?
iburlakov

Odpowiedzi:

319

Cóż, proste opcje to:

  • string.Format:

    string x = string.Format("first line{0}second line", Environment.NewLine);
  • Konkatenacja ciągów:

    string x = "first line" + Environment.NewLine + "second line";
  • Interpolacja ciągów (w C # 6 i nowszych):

    string x = $"first line{Environment.NewLine}second line";

Możesz też użyć \ n wszędzie i zamienić:

string x = "first line\nsecond line\nthird line".Replace("\n",
                                                         Environment.NewLine);

Zauważ, że nie możesz uczynić tego ciągiem stałym , ponieważ wartość Environment.NewLinebędzie dostępna tylko w czasie wykonywania.

Jon Skeet
źródło
1
Cóż, dzięki oczywiście, ale miałem na myśli unikanie używania Environment.NewLine, moje pytanie brzmiało, czy istnieje literał „/ newline”.
Captain Comic
2
@Captain: Dlaczego chcesz tego uniknąć Environment.NewLine? Wręcz przeciwnie, dobrze jest go używać
abatishchev
18
@abatishchev: W niektórych miejscach jest to dobra praktyka. U innych tak nie jest. Naprawdę musisz wiedzieć, że chcesz korzystać z platformy specyficznej dla platformy. Na przykład nie jest dobrym pomysłem, jeśli używasz protokołu sieciowego, który powinien sam definiować terminatory linii.
Jon Skeet
1
@Captain Komiks: Moje ostatnie zdanie wyjaśnia, dlaczego nie może być dosłowne escape - nie można umieścić go w metadanych dla stałej strun, bo to nie jest wartość stała.
Jon Skeet
1
Tak, być może byłem niechętny, ponieważ obie opcje: jedna używająca operatora plus, a druga używająca metody Format to spory narzut, gdzie wstrzyknięcie literału '\ newline' byłoby najszybszym sposobem. Ale jak powiedział Jon dosłownie, gdyby NewLine istniał, musiałby być dynamiczny i zależny od platformy.
Captain Comic
33

Jeśli chcesz mieć ciąg znaków const zawierający Environment.NewLine, możesz zrobić coś takiego:

const string stringWithNewLine =
@"first line
second line
third line";

EDYTOWAĆ

Ponieważ jest to ciąg znaków const, odbywa się to w czasie kompilacji, dlatego jest to interpretacja nowej linii przez kompilator. Nie mogę znaleźć odniesienia wyjaśniającego to zachowanie, ale mogę udowodnić, że działa zgodnie z przeznaczeniem. Skompilowałem ten kod zarówno w systemie Windows, jak i Ubuntu (z Mono), a następnie zdemontowałem i oto wyniki:

Demontaż w systemie Windows Demontuj na Ubuntu

Jak widać, w systemie Windows znaki nowej linii są interpretowane jako \ r \ n, aw systemie Ubuntu jako \ n

Tal Jerome
źródło
1
Kompilator automatycznie dodaje Environment.NewLine między każdą linią tekstu. Zatem ciąg jest interpretowany jako: „pierwsza linia” + Environment.NewLine + „druga linia” + Environment.NewLine + „trzecia linia”
Tal Jerome
3
+1 Mało znany sposób wstawiania znaków nowej linii w literałach łańcuchowych. Czy istnieje odniesienie do określonego zachowania? Czy to naprawdę Environment.NewLine, czy jest to definicja nowej linii w kompilatorze?
Grimace of Despair
1
Czy na pewno to nie znak nowej linii edytora kodu zostanie tam wstawiony? Jeśli skopiujesz i wkleisz ten kod do edytora w systemie Windows, prawdopodobnie zostanie on przekonwertowany na \ r \ n. Zrób to samo na platformie podobnej do Uniksa, a prawdopodobnie zostanie przekonwertowany na \ n.
Xiyng
Uważaj z tym. Jeśli wyewidencjonujesz kod na serwerze CI / CD (jak Teamcity, wyewidencjonowanie po stronie serwera), zmieni to CRLF na LF i nie będzie nowych linii w łańcuchu.
Leszek P
13
var sb = new StringBuilder();
sb.Append(first);
sb.AppendLine(); // which is equal to Append(Environment.NewLine);
sb.Append(second);
return sb.ToString();
abatishchev
źródło
2
Dlaczego miałbyś to zrobić zamiast używać first + Environment.NewLine + secondbardziej wydajnego i (IMO) łatwiejszego do odczytania?
Jon Skeet
@Jon: Bardziej wydajne, naprawdę? Myślałem, że String.Formatto da 1 ciąg na raz (ale wewnętrznie jest trochę powolny z powodu konkatenacji specyficznych dla kultury itp.), Podczas gdy konkatenacja ciągów - 1 wynikowy + 1 tymczasowy, prawda?
abatishchev
1
@abatishchev: kompilator konwertuje str + str + str na String.Concatenate, co bezpośrednio buduje tylko jeden ciąg wyjściowy (IIRC, jeśli ciągi są literałami, konkatenacja jest wykonywana w kompilatorze.
Richard
@Richard: tzn. Wielokrotne, ale jednowierszowe konkatenacje ciągów ( "a"+b+"c"+ditp.) Według wydajności są równe pojedynczemu? Lub po prostu przekonwertowany String.Concatenate(a,b,c,d,etc), prawda?
abatishchev
@abatishchev: Dlatego nie zasugerowałem string.Formatw komentarzu. Łączenie ciągów nie da żadnych tymczasowych ciągów, ponieważ kompilator wywoła string.Concat(first, Environment.NewLine, second).
Jon Skeet
3

Jeszcze jeden sposób wygodnego umieszczenia Environment.NewLine w ciągu formatu. Chodzi o to, aby utworzyć metodę rozszerzającą ciąg, która formatuje ciąg w zwykły sposób, ale także zastępuje {nl} w tekście przez Environment.NewLine

Stosowanie

   " X={0} {nl} Y={1}{nl} X+Y={2}".FormatIt(1, 2, 1+2);
   gives:
    X=1
    Y=2
    X+Y=3

Kod

    ///<summary>
    /// Use "string".FormatIt(...) instead of string.Format("string, ...)
    /// Use {nl} in text to insert Environment.NewLine 
    ///</summary>
    ///<exception cref="ArgumentNullException">If format is null</exception>
    [StringFormatMethod("format")]
    public static string FormatIt(this string format, params object[] args)
    {
        if (format == null) throw new ArgumentNullException("format");

        return string.Format(format.Replace("{nl}", Environment.NewLine), args);
    }

Uwaga

  1. Jeśli chcesz, aby ReSharper podświetlał twoje parametry, dodaj atrybut do powyższej metody

    [StringFormatMethod ("format")]

  2. Ta implementacja jest oczywiście mniej wydajna niż tylko String.Format

  3. Może kogoś, kto byłby zainteresowany tym pytaniem, byłby również zainteresowany kolejnym pytaniem: Nazwane formatowanie ciągów w C #

MajesticRa
źródło
2
string myText =
    @"<div class=""firstLine""></div>
      <div class=""secondLine""></div>
      <div class=""thirdLine""></div>";

To nie to:

string myText =
@"<div class=\"firstLine\"></div>
  <div class=\"secondLine\"></div>
  <div class=\"thirdLine\"></div>";
Hakkı Eser
źródło
1
static class MyClass
{
   public const string NewLine="\n";
}

string x = "first line" + MyClass.NewLine + "second line"

źródło
3
-1: System już definiuje Environment.NewLine- zobacz inne odpowiedzi.
Richard
@Richard OP, o ile mogłem go zrozumieć, chce wykorzystać inlined ciągiem znaków, czyliconst string
abatishchev
@Richard Environment.NewLine jest statyczna, a nie
1

nowsze wersje .net pozwalają na użycie znaku $ przed literałem, co pozwala na użycie zmiennych wewnątrz, jak poniżej:

var x = $"Line 1{Environment.NewLine}Line 2{Environment.NewLine}Line 3";
DanielK
źródło
1
Odrobina kontekstu nie byłaby zła.
croxy
1
To nie daje odpowiedzi na pytanie. Gdy zdobędziesz wystarczającą reputację , będziesz mógł komentować każdy post ; zamiast tego udziel odpowiedzi, które nie wymagają wyjaśnień od pytającego . - Z recenzji
H. Pauwelyn
@ H.Pauwelyn ツ: Dzięki za opinie. Dodałem trochę kontekstu. Z mojego punktu widzenia rozwiązanie zdecydowanie odpowiada na pytanie.
DanielK
0

Jeśli naprawdę chcesz, aby ciąg New Line był stałą, możesz to zrobić:

public readonly string myVar = Environment.NewLine;

Użytkownik słowa kluczowego readonly w C # oznacza, że ​​ta zmienna może być przypisana tylko raz. Dokumentację na ten temat znajdziesz tutaj . Pozwala na deklarację stałej zmiennej, której wartość nie jest znana do czasu wykonania.

wizard07KSU
źródło
0

Bardziej podoba mi się „pythonowy sposób”

List<string> lines = new List<string> {
    "line1",
    "line2",
    String.Format("{0} - {1} | {2}", 
        someVar,
        othervar, 
        thirdVar
    )
};

if(foo)
    lines.Add("line3");

return String.Join(Environment.NewLine, lines);
postrzegać
źródło
0

Jeśli pracujesz z aplikacją internetową, możesz spróbować tego.

StringBuilder sb = new StringBuilder();
sb.AppendLine("Some text with line one");
sb.AppendLine("Some mpre text with line two");
MyLabel.Text = sb.ToString().Replace(Environment.NewLine, "<br />")
Tejas Bagade
źródło
0

Jeśli rozumiem pytanie: para, "\r\n"aby uzyskać tę nową linię poniżej w textbox. Mój przykład zadziałał -

   string s1 = comboBox1.Text;     // s1 is the variable assigned to box 1, etc.
   string s2 = comboBox2.Text;

   string both = s1 + "\r\n" + s2;
   textBox1.Text = both;

Typowa odpowiedź może być s1 s2 w text boxprzy użyciu zdefiniowanego stylu typu.

Charles F.
źródło
-1

Tutaj Environment.NewLine nie działa.

I umieścić „ < br / > ” na sznurku i pracował.

Dawny:

ltrYourLiteral.Text = "Pierwszy wiersz <. br / > Second Line.";

Fábio
źródło