Warum gibt es kein Char.Empty wie String.Empty?

259

Gibt es einen Grund dafür? Ich frage, denn wenn Sie viele leere Zeichen verwenden müssen, geraten Sie in die gleiche Situation wie wenn Sie viele leere Zeichenfolgen verwenden würden.

Bearbeiten: Der Grund für diese Verwendung war folgender:

myString.Replace ('c', '')

Entfernen Sie also alle Instanzen von 'c' aus myString.

Joan Venge
quelle
1
Ja, ich habe dieses Wort verwendet, weil ich kein besseres Wort hatte. dh die empfohlene Verwendung von String.Empty anstelle von "".
Joan Venge
3
Wenn Sie besorgt sind über versehentlich einen Tippfehler ‚‘ manchmal, warum nicht nur einfach wickeln Sie die Funktionalität in einem Verlängerungsverfahren entlang der Linien von RemoveAll(this string s, params char[] toRemove)? Die Absicht wird klar kommuniziert und Sie riskieren nichts falsch zu tippen.
Bzlm
12
@Henk - Der einzige Grund, warum ich string.Empty verwende, ist, dass ich finde, dass das von Empty bereitgestellte Null-Objekt die Absicht besser ausdrückt als leere Anführungszeichen. Leere Anführungszeichen können aus einem Zusammenführungsproblem oder einem verpfuschten Gedanken resultieren, oder es kann die eigentliche Absicht dieses Codes sein, während Empty mir ausdrücklich mitteilt, dass der Entwickler beabsichtigt hat, dass diese Zeichenfolge keine Daten enthält.
Ritch Melton
3
Es gibt einen Unterschied zwischen "" und der Zeichenfolge. Leer. Eigentlich nicht, dass es irgendjemand interessiert, aber "" erstellt ein Objekt, während string.Empty ein bereits erstelltes verwendet. Aber auch hier ist es so klein, dass nur besondere Situationen einen Unterschied machen würden
marcelo-ferraz
1
@ marcelo-ferrazm, über ""erstellt ein Objekt : Nein, tut es nicht.
Henk Holterman

Antworten:

272

Es gibt keinen leeren Saibling. Das nächstgelegene '\0'Zeichen ist das Unicode-Zeichen "null". Warum sollten Sie ein separates Feld dafür benötigen, da Sie dies in Zeichenfolgenliterale einbetten oder ganz einfach selbst ausdrücken können? Ebenso gelten die Argumente "Es ist leicht zu verwirren ""und " "" nicht '\0'.

Wenn Sie ein Beispiel geben könnten, wo Sie es verwenden möchten und warum Sie denken, dass es besser wäre, könnte das helfen ...

Jon Skeet
quelle
2
Ist das \ 0 nicht das 'Ende des Byte-Array'-Zeichens? Oder verwechsle ich etwas anderes?
Bertvan
5
@ Bertvan: Warum sollte am Ende eines Byte- Arrays ein Zeichen stehen ? Es wird jedoch für "nullterminierte" Zeichenfolgen verwendet, ja.
Jon Skeet
35
Char.MinValue ist besser als '\ 0'
Aliostad
10
@Aliostad: Aus Interesse, wenn es ein ähnliches Feld für Int32.Zerogäbe, würden Sie das anstelle der wörtlichen 0 verwenden? Wenn nicht, was ist der Unterschied hier?
Jon Skeet
7
@Adam, @Jon - wie lautet der Code für die Glocke? Oder Backspace besser, denken Sie denken ... Oder vielleicht ist es einfach besser, Char.Backspace zu schreiben, anstatt zu denken? Ein weiterer Grund - Sie sagen, es ist besser, '0' für den Terminator zu schreiben, stattdessen Char.Terminator zu sagen, ist es jedoch nicht - es ist zu einfach, einen Tippfehler zu machen (vollständig kompiliert, siehe oben), aber versuchen Sie zu schreiben Char.Termnator. Es gibt genug Gründe für mich, nicht überprüfbare Rohwerte zu vermeiden (Weltraummissionen scheiterten an solchen dummen Tippfehlern).
Greenoldman
87

Ein Zeichen ist im Gegensatz zu einer Zeichenfolge eine diskrete Sache mit einer festen Größe. Eine Zeichenfolge ist wirklich ein Container mit Zeichen.

Char.Empty macht in diesem Zusammenhang also keinen Sinn. Wenn Sie ein Zeichen haben, ist es nicht leer.

Joe
quelle
3
Genau richtig. Es ist sinnvoll zu fragen, ob ein Container leer ist oder nicht. Es macht keinen Sinn, nach einem int oder float zu fragen, oder char ist leer.
TED
1
@ Joe: Wie kann dann eine Zeichenfolge leer sein, wenn eine Zeichenfolge eine Sammlung von (nicht leeren) Zeichen ist? Wahrscheinlich dumm, sorry ...
user1477388
9
Da eine Zeichenfolge nicht die einzelnen Objekte sind, ist sie die Sammlung. Denken Sie an einen Eimer mit Steinen. Ich kann keinen leeren Stein haben. Aber ich kann einen leeren Eimer haben.
Joe
2
Ich würde es als "ein Zeichen ist ein primitiver Werttyp und eine Zeichenfolge ist ein nicht primitiver Referenztyp" ausdrücken.
Samis
3
Das ist die wahre Antwort.
Gandalf458
31

Es gibt keinen leeren Charakter. Es enthält immer etwas . Sogar '\ 0' ist ein Zeichen.

Philippe Leybaert
quelle
28

Verwenden Sie, Char.MinValuewas genauso funktioniert wie '\ 0'. Aber sei vorsichtig, es ist nicht dasselbe wie String.Empty.

Aliostad
quelle
Danke, habe das noch nie gesehen. Wissen Sie, ob es in myString.Replace ('c', Char.MinValue) funktioniert? Ich sollte es versuchen.
Joan Venge
19

Sie könnten nullbare Zeichen verwenden.

char? c
paquetp
quelle
Dies erlaubt ''? Oder einfach null?
Joan Venge
In Ihrem Fall könnten Sie dies tun: myString.Replace ("c", (c == null? "": C.ToString ()))
paquetp
12

Wenn Sie nicht die gesamte Zeichenfolge benötigen, können Sie die verzögerte Ausführung nutzen:

public static class StringExtensions
{
    public static IEnumerable<char> RemoveChar(this IEnumerable<char> originalString, char removingChar)
    {
        return originalString.Where(@char => @char != removingChar);
    }
}

Sie können sogar mehrere Zeichen kombinieren ...

string veryLongText = "abcdefghijk...";

IEnumerable<char> firstFiveCharsWithoutCsAndDs = veryLongText
            .RemoveChar('c')
            .RemoveChar('d')
            .Take(5);

... und nur die ersten 7 Zeichen werden ausgewertet :)

EDIT: oder noch besser:

public static class StringExtensions
{
    public static IEnumerable<char> RemoveChars(this IEnumerable<char> originalString,
        params char[] removingChars)
    {
        return originalString.Except(removingChars);
    }
}

und seine Verwendung:

        var veryLongText = "abcdefghijk...";
        IEnumerable<char> firstFiveCharsWithoutCsAndDs = veryLongText
            .RemoveChars('c', 'd')
            .Take(5)
            .ToArray(); //to prevent multiple execution of "RemoveChars"
Notoriousxl
quelle
@Joan: danke ... auch wenn "Genius" etwas übertrieben ist: P (Ich weiß nicht, wie gut es ist, wenn
Notoriousxl
1
Gestern habe ich vergessen: Achten Sie darauf, wie Sie die Ergebnisvariable "firstFiveCharsWithoutCsAndDs" verwenden. Wenn Sie es nicht an eine andere "Yield" -Methode (wie die von LINQ) übergeben möchten, rufen Sie sofort nach "Take (5)" ein ".ToArray ()" auf. Andernfalls wird "RemoveChars + Take". Die Kette wird jedes Mal ausgeführt, wenn Sie auf "traditionelle" Weise auf die Variable zugreifen (z. B. jedes Mal, wenn Sie ein "Count ()" darauf aufrufen oder wenn Sie sie in einem Foreach ohne "Yield Return" durchlaufen)
Notoriousxl
+1 schönes Denken. aber dies kann nicht so wartbar oder effizient sein wie der grundlegende Ansatz :)
Nawfal
1
@nawfal Effizienzmäßig haben Sie Recht, aber ich denke, dass myString.Except ("c") deklarativer ist als myString.Replace ('c', ''): P (und es skaliert ziemlich gut: myString.Except ( "aeiou"))
Notoriousxl
7
myString = myString.Replace('c'.ToString(), "");

OK, dies ist nicht besonders elegant zum Entfernen von Buchstaben, da die .Replace-Methode eine Überladung aufweist, die Zeichenfolgenparameter akzeptiert. Dies funktioniert jedoch zum Entfernen von Wagenrückläufen, Zeilenvorschüben, Tabulatoren usw. In diesem Beispiel werden Tabulatorzeichen entfernt:

myString = myString.Replace('\t'.ToString(), "");
Mike Taverne
quelle
6

Aus dem gleichen Grund gibt es keine int.Empty. Container können leer sein. Skalarwerte können nicht sein. Wenn Sie 0 meinen (was nicht leer ist), dann verwenden Sie '\0'. Wenn du meinst null, dann benutze null:)

zehn vier
quelle
2
null ist nicht möglich, da char ein ValueType ist. Sie müssten char verwenden? um ihm null zuweisen zu können.
Femaref
Sie sollten es nullbar machen. siehe meine Antwort
paquetp
5

Ein Zeichen ist ein Werttyp, daher kann sein Wert nicht null sein. (Es sei denn, es ist in einen Nullable-Container verpackt).

Da es nicht null sein kann, enthält in einen numerischen Code und jeder Code ist einem Zeichen zugeordnet.

Epotter
quelle
4

Keine Antwort auf Ihre Frage, aber um einen Standard zu kennzeichnen char, können Sie einfach verwenden

default(char)

das ist das gleiche wie char.MinValuedas wiederum ist das gleiche wie \0. Man sollte es jedoch nicht für so etwas wie eine leere Zeichenfolge verwenden.

nawfal
quelle
1

Beantwortet Ihre erste Frage nicht - aber für das spezifische Problem, das Sie hatten, können Sie einfach Zeichenfolgen anstelle von Zeichen verwenden, oder?:

myString.Replace("c", "")

Gibt es einen Grund, warum Sie das nicht wollen?

Ian Grainger
quelle
1

Sie können Ihre Zeichenfolge auch zeichenweise neu erstellen, mit Ausnahme der Zeichen, die Sie entfernen möchten.

Hier ist eine Erweiterungsmethode, um dies zu tun:

    static public string RemoveAny(this string s, string charsToRemove)
    {
        var result = "";
        foreach (var c in s)
            if (charsToRemove.Contains(c))
                continue;
            else
                result += c;

        return result;
    }

Es ist nicht schick oder schick, aber es funktioniert gut.

Verwenden Sie wie folgt:

string newString = "My_String".RemoveAny("_"); //yields "MyString"
C. Tewalt
quelle
Verwenden Sie ein StringBuilderfür result. Warum nicht einwickeln return s.Replace(charsToRemove,"");?
Aloisdg wechselt zu codidact.com
1

Wenn Sie Zeichen entfernen möchten, die eine bestimmte Bedingung erfüllen, können Sie Folgendes verwenden:

string s = "SoMEthInG";
s = new string(s.Where(c => char.IsUpper(c)).ToArray());

(Dadurch bleiben nur die Großbuchstaben in der Zeichenfolge.)

Mit anderen Worten, Sie können die Zeichenfolge als "verwenden" IEnumerable<char>, Änderungen daran vornehmen und sie dann wie oben gezeigt wieder in eine Zeichenfolge konvertieren.

Dies ermöglicht es wiederum, nicht nur ein bestimmtes Zeichen aufgrund des Lambda-Ausdrucks zu entfernen, sondern dies auch, wenn Sie den Lambda-Ausdruck folgendermaßen ändern : c => c != 't'.

florien
quelle
0

Wie wäre es mit BOM , dem magischen Charakter, den Microsoft zum Start von Dateien hinzufügt (zumindest XML)?

Arto Viitanen
quelle
Der Wortlaut auf Wikipedia hier ist ziemlich unglücklich; Die Stückliste ist in diesem Zusammenhang kein Zeichen. Und was genau ist deine Frage? :)
bzlm
@onemach, also, ob myString.Replace ('c', '')durch erreicht werden könnte myString.Replace ('c', UTF_BOM). Dann würde ich sagen, die Antwort lautet "wie wäre es nicht mit ...".
Bzlm
0

Wenn Sie das leere Zeichen in der Zeichenfolge entfernen möchten, funktioniert Folgendes: Konvertieren Sie es einfach in eine beliebige Datentypdarstellung. Vielen Dank,

private void button1_Click(object sender, EventArgs e)
    {

        Int32 i;

        String name;

        Int32[] array_number = new int[100];

        name = "1 3  5  17   8    9    6";

        name = name.Replace(' ', 'x');

        char[] chr = name.ToCharArray();


        for (i = 0; i < name.Length; i++)
        {
            if ((chr[i] != 'x'))
            {
                array_number[i] = Convert.ToInt32(chr[i].ToString());
                MessageBox.Show(array_number[i].ToString());
            }

        }

    }
Alexander Zaldostanov
quelle
0

In Bezug auf die C # -Sprache ist Folgendes möglicherweise nicht sehr sinnvoll. Und dies ist keine direkte Antwort auf die Frage. Aber Fowlloing ist das, was ich in einem meiner Geschäftsszenarien getan habe

        char? myCharFromUI = Convert.ToChar(" ");
        string myStringForDatabaseInsert = myCharFromUI.ToString().Trim();
        if (String.IsNullOrEmpty(myStringForDatabaseInsert.Trim()))
        {
            Console.Write("Success");
        }

Die nullund white spacehatten unterschiedliche Geschäftsabläufe in meinem Projekt. Beim Einfügen in die Datenbank muss ich empty stringin die Datenbank einfügen , wenn es sich um Leerzeichen handelt.

LCJ
quelle
0

Ich weiß, dass dieser ziemlich alt ist, aber ich bin kürzlich auf ein Problem gestoßen, bei dem mehrere Ersetzungen vorgenommen werden mussten, um einen Dateinamen sicher zu machen. Erstens ist in der neuesten .NET-Zeichenfolge.Replace-Funktion null das Äquivalent zu einem leeren Zeichen. Was jedoch in .Net fehlt, ist ein einfaches Ersetzen aller Zeichen in einem Array durch das gewünschte Zeichen. Bitte verweisen Sie auf den folgenden Code (wird zum Testen in LinqPad ausgeführt).

// LinqPad .ReplaceAll and SafeFileName
void Main()
{

    ("a:B:C").Replace(":", "_").Dump();                     // can only replace 1 character for one character => a_B_C
    ("a:B:C").Replace(":", null).Dump();                    // null replaces with empty => aBC
    ("a:B*C").Replace(":", null).Replace("*",null).Dump();  // Have to chain for multiples 

    // Need a ReplaceAll, so I don't have to chain calls


    ("abc/123.txt").SafeFileName().Dump();
    ("abc/1/2/3.txt").SafeFileName().Dump();
    ("a:bc/1/2/3.txt").SafeFileName().Dump();
    ("a:bc/1/2/3.txt").SafeFileName('_').Dump();
    //("abc/123").SafeFileName(':').Dump(); // Throws exception as expected

}


static class StringExtensions
{

    public static string SafeFileName(this string value, char? replacement = null)
    {
        return value.ReplaceAll(replacement, ':','*','?','"','<','>', '|', '/', '\\');
    }

    public static string ReplaceAll(this string value, char? replacement, params char[] charsToGo){

        if(replacement.HasValue == false){
                return string.Join("", value.AsEnumerable().Where(x => charsToGo.Contains(x) == false));
        }
        else{

            if(charsToGo.Contains(replacement.Value)){
                throw new ArgumentException(string.Format("Replacement '{0}' is invalid.  ", replacement), "replacement");
            }

            return string.Join("", value.AsEnumerable().Select(x => charsToGo.Contains(x) == true ? replacement : x));
        }

    }

}
Jim
quelle
-3

verwenden

myString.Replace ("c", "")
Chintan
quelle
2
Dies ist ein Duplikat einer Antwort von Ian Grainger aus dem Jahr 2013.
Joe Gayetty
-3

Der einfachste Weg, ein Zeichen pauschal aus der Zeichenfolge zu entfernen, besteht darin, es zuzuschneiden

cl = cl.Trim(' ');

Entfernt alle Leerzeichen in einer Zeichenfolge

MrSmudge
quelle
Dies ist hilfreich, wenn Sie use .Replace ('c', '') verwenden möchten, um andere Leerzeichen zu entfernen. Aber es ist hilfreicher als viele andere Antworten.
Jan
1
Nein das ist falsch! Trim entferne nur Zeichen vom Anfang und Ende eines Strings, der nicht in der Mitte liegt
userSteve