Pourquoi n'y a-t-il pas de Char.Empty comme String.Empty?

259

Y a-t-il une raison à cela? Je demande parce que si vous avez besoin d'utiliser beaucoup de caractères vides, vous vous retrouvez dans la même situation que lorsque vous utilisez beaucoup de chaînes vides.

Edit: La raison de cette utilisation était la suivante:

myString.Replace ('c', '')

Supprimez donc toutes les instances de 'c' de myString.

Joan Venge
la source
1
Ouais j'ai utilisé ce mot faute d'un meilleur mot. c'est-à-dire la manière recommandée d'utiliser String.Empty au lieu de "".
Joan Venge
3
Si vous êtes préoccupé par une erreur de frappe accidentelle '' parfois, pourquoi ne pas simplement envelopper simplement la fonctionnalité dans une méthode d'extension dans le sens de RemoveAll(this string s, params char[] toRemove)? L'intention sera clairement communiquée et vous ne risquez pas de taper quoi que ce soit.
bzlm
12
@Henk - La seule raison pour laquelle j'utilise string.Empty est parce que je trouve que l'objet null fourni par Empty exprime mieux l'intention que les guillemets vides. Des guillemets vides pourraient résulter d'un problème de fusion, ou d'une pensée erronée, ou cela pourrait être l'intention réelle de ce code, alors qu'Empty me dit explicitement que le développeur avait l'intention que cette chaîne ne contienne pas de données.
Ritch Melton
3
Il existe une différence entre "" et la chaîne. Vide. Pas que quelqu'un s'en soucie vraiment, mais "" crée un objet, alors que string.Empty utilise un objet déjà créé. Mais encore une fois, il est si petit, que seules des situations spéciales feraient une différence
marcelo-ferraz
1
@ marcelo-ferrazm, about ""crée un objet : Non, ce n'est pas le cas.
Henk Holterman

Réponses:

272

Il n'y a pas de char vide. Le plus proche que vous pouvez obtenir est '\0'le caractère "null" Unicode. Étant donné que vous pouvez intégrer cela dans des littéraux de chaîne ou l'exprimer très facilement, pourquoi voudriez-vous un champ séparé pour cela? De même, les arguments "c'est facile à confondre ""et " "" ne s'appliquent pas '\0'.

Si vous pouviez donner un exemple de l'endroit où vous souhaitez l'utiliser et pourquoi vous pensez que ce serait mieux, cela pourrait aider ...

Jon Skeet
la source
2
Le \ 0 n'est-il pas le caractère de «fin du tableau d'octets»? Ou suis-je confus avec autre chose?
Bertvan
5
@Bertvan: Pourquoi y aurait-il un caractère à la fin d'un tableau d' octets ? Il est cependant utilisé pour les chaînes "terminées par null".
Jon Skeet
35
Char.MinValue est meilleur que '\ 0'
Aliostad
10
@Aliostad: Par intérêt, s'il y avait un champ similaire pour Int32.Zero, l'utiliseriez-vous à la place du 0 littéral? Sinon, quelle est la différence ici?
Jon Skeet
7
@Adam, @Jon - quel est le code pour bell? Ou mieux revenir en arrière, penser, penser ... Ou peut-être qu'au lieu de penser, il est juste préférable d'écrire Car.Backspace? Une autre raison - vous dites qu'il vaut mieux écrire «0» pour terminator, à la place, dites Char.Terminator, mais ce n'est pas le cas - il est trop facile de faire une faute de frappe (entièrement compilé, voir ci-dessus), mais essayez d'écrire Char Terminator. Il y a suffisamment de raisons pour moi d'éviter les valeurs brutes non vérifiables (les missions spatiales ont échoué à cause de fautes de frappe stupides comme ça).
greenoldman
87

Un char, contrairement à une chaîne, est une chose discrète avec une taille fixe. Une chaîne est vraiment un conteneur de caractères.

Donc, Char.Empty n'a pas vraiment de sens dans ce contexte. Si vous avez un caractère, il n'est pas vide.

Joe
la source
3
Exactement. Il est logique de demander si un conteneur est vide ou non. Cela n'a aucun sens de demander à un int ou un float ou char est vide.
TED
1
@Joe: Comment une chaîne peut-elle être vide si une chaîne est une collection de caractères (non vides)? Probablement stupide, désolé ...
user1477388
9
Parce qu'une chaîne n'est pas les objets individuels, c'est la collection. Pensez à un seau de rochers. Je ne peux pas avoir un rocher vide. Mais je peux avoir un seau vide.
Joe
2
Je dirais que "un char est un type de valeur primitif et une chaîne est un type de référence non primitif".
samis
3
Telle est la vraie réponse.
Gandalf458
31

Il n'y a pas de personnage vide. Il contient toujours quelque chose . Même '\ 0' est un caractère.

Philippe Leybaert
la source
28

Utilisation Char.MinValuequi fonctionne de la même manière que «\ 0». Mais attention ce n'est pas pareil String.Empty.

Aliostad
la source
Merci, je n'ai jamais vu ça avant. Savez-vous si cela fonctionne dans myString.Replace ('c', Char.MinValue)? Je devrais essayer.
Joan Venge
19

Vous pouvez utiliser des caractères nullables .

char? c
paquetp
la source
Ceci permet ''? Ou tout simplement nul?
Joan Venge
Dans votre cas, vous pouvez le faire: myString.Replace ("c", (c == null? "": C.ToString ()))
paquetp le
12

Si vous n'avez pas besoin de la chaîne entière, vous pouvez profiter de l'exécution retardée:

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

Vous pouvez même combiner plusieurs caractères ...

string veryLongText = "abcdefghijk...";

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

... et seuls les 7 premiers caractères seront évalués :)

EDIT: ou encore mieux:

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

et son utilisation:

        var veryLongText = "abcdefghijk...";
        IEnumerable<char> firstFiveCharsWithoutCsAndDs = veryLongText
            .RemoveChars('c', 'd')
            .Take(5)
            .ToArray(); //to prevent multiple execution of "RemoveChars"
Notoriousxl
la source
@Joan: merci ... même si "Genius" c'est un peu exagéré: P (je ne connais pas ses performances lorsque le retrait de
Notoriousxl
1
Hier, j'ai oublié: faites attention à la façon dont vous utilisez la variable de résultat "firstFiveCharsWithoutCsAndDs". Si vous ne voulez pas le passer à une autre méthode "yield" (comme celles de LINQ), appelez immédiatement un ".ToArray ()" après le "Take (5)" ... sinon, le "RemoveChars + Take" la chaîne sera exécutée chaque fois que vous accédez à la variable de façon "traditionnelle" (par exemple, chaque fois que vous appelez un "Count ()" dessus, ou lorsque vous la parcourez dans un foreach sans "return return")
Notoriousxl
+1 belle réflexion. mais cela ne peut pas être aussi maintenable ou efficace que l'approche de base :)
nawfal
1
@nawfal en termes d'efficacité, vous avez raison, mais je pense que myString.Except ("c") est plus déclaratif que myString.Replace ('c', ''): P (et il évolue assez bien: myString.Except ( "aeiou"))
Notoriousxl
7
myString = myString.Replace('c'.ToString(), "");

OK, ce n'est pas particulièrement élégant pour supprimer des lettres, car la méthode .Replace a une surcharge qui prend des paramètres de chaîne. Mais cela fonctionne pour supprimer les retours chariot, les sauts de ligne, les tabulations, etc. Cet exemple supprime les caractères de tabulation:

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

la même raison qu'il n'y en a pas int.Empty. Les conteneurs peuvent être vides. Les valeurs scalaires ne peuvent pas l'être. Si vous voulez dire 0 (qui n'est pas vide), utilisez alors '\0'. Si vous voulez dire null, utilisez null:)

dix quatre
la source
2
null n'est pas possible car char est un ValueType. Vous devez utiliser char? pour pouvoir lui attribuer null.
Femaref
vous devriez le rendre nul. voir ma réponse
paquetp
5

Un caractère est un type de valeur, sa valeur ne peut donc pas être nulle. (À moins qu'il ne soit emballé dans un contenant Nullable).

Puisqu'il ne peut pas être nul, in contient du code numérique et chaque code est mappé à un caractère.

epotter
la source
4

Pas une réponse à votre question, mais pour désigner une valeur par défaut, charvous pouvez utiliser simplement

default(char)

qui est le même que celui char.MinValuequi à son tour est le même que \0. Il ne faut cependant pas utiliser if pour quelque chose comme une chaîne vide.

nawfal
la source
1

Ne répond pas à votre première question - mais pour le problème spécifique que vous avez rencontré, vous pouvez simplement utiliser des chaînes au lieu de caractères, non?:

myString.Replace("c", "")

Il y a une raison pour laquelle vous ne voudriez pas faire ça?

Ian Grainger
la source
1

Vous pouvez également reconstruire votre chaîne caractère par caractère, à l'exclusion des caractères dont vous souhaitez vous débarrasser.

Voici une méthode d'extension pour ce faire:

    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;
    }

Ce n'est pas lisse ou sophistiqué, mais cela fonctionne bien.

Utilisez comme ceci:

string newString = "My_String".RemoveAny("_"); //yields "MyString"
C. Tewalt
la source
Utilisez un StringBuilderfor result. Pourquoi ne pas envelopper return s.Replace(charsToRemove,"");?
aloisdg passe à codidact.com le
1

Si vous souhaitez supprimer des caractères qui remplissent une condition spécifique, vous pouvez utiliser ceci:

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

(Cela ne laissera que les caractères majuscules dans la chaîne.)

En d'autres termes, vous pouvez "utiliser" la chaîne comme IEnumerable<char> , y apporter des modifications, puis la reconvertir en chaîne comme indiqué ci-dessus.

Encore une fois, cela permet non seulement de supprimer un char spécifique en raison de l'expression lambda, mais vous pouvez le faire si vous changez l'expression lambda comme ceci: c => c != 't'.

florien
la source
0

Que diriez-vous de BOM , le personnage magique que Microsoft ajoute au début des fichiers (au moins XML)?

Arto Viitanen
la source
Le libellé sur Wikipédia ici est assez regrettable; la nomenclature n'est pas un personnage dans ce contexte. Et quelle est votre question exactement? :)
bzlm
@onemach, donc, si cela myString.Replace ('c', '')pourrait être réalisé par myString.Replace ('c', UTF_BOM). Alors je dirais que la réponse est "pourquoi pas ...".
bzlm
0

si vous souhaitez éliminer le caractère vide dans la chaîne, ce qui suit fonctionnera, convertissez-le simplement en n'importe quelle représentation de type de données que vous souhaitez. Merci,

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
la source
0

En termes de langage C #, les éléments suivants peuvent ne pas avoir beaucoup de sens. Et ce n'est pas une réponse directe à la question. Mais fowlloing est ce que j'ai fait dans l'un de mes scénarios d'entreprise

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

Le nullet white spaceavait des flux commerciaux différents dans mon projet. Lors de l'insertion dans la base de données, je dois insérer empty stringdans la base de données s'il s'agit d'un espace blanc.

LCJ
la source
0

Je sais que celui-ci est assez ancien, mais j'ai récemment rencontré un problème avec le fait de devoir faire plusieurs remplacements pour sécuriser un nom de fichier. Tout d'abord, dans la dernière chaîne .NET, la fonction de remplacement null est l'équivalent d'un caractère vide. Cela dit, ce qui manque dans .Net est un simple remplacement de tout ce qui remplacera n'importe quel caractère d'un tableau par le caractère souhaité. N'hésitez pas à faire référence au code ci-dessous (s'exécute dans LinqPad pour les tests).

// 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
la source
-3

utilisation

myString.Replace ("c", "")
Chintan
la source
2
Ceci est un double d'une réponse de 2013 par Ian Grainger.
Joe Gayetty
-3

Le moyen le plus simple de supprimer un caractère de la chaîne est de le couper

cl = cl.Trim(' ');

Supprime tous les espaces d'une chaîne

MrSmudge
la source
Cela est utile si l'on veut utiliser .Replace ('c', '') avec l'inconvénient de supprimer d'autres espaces blancs. Mais c'est plus utile que beaucoup d'autres réponses données.
Jan
1
Non c'est faux! Le trim supprime uniquement les caractères du début et de la fin d'une chaîne qui n'est pas au milieu
userSteve