Por que não existe Char.Empty como String.Empty?

259

Existe uma razão para isso? Estou perguntando, porque se você precisasse usar muitos caracteres vazios, entraria na mesma situação que usaria quando usasse muitas strings vazias.

Edit: O motivo desse uso foi o seguinte:

myString.Replace ('c', '')

Portanto, remova todas as instâncias de 'c's do myString.

Joan Venge
fonte
1
Sim, eu usei essa palavra por falta de uma palavra melhor. ou seja, a maneira recomendada de usar String.Empty em vez de "".
Joan Venge
3
Se você está preocupado com erros de digitação acidental '' às vezes, por que não simplesmente agrupar a funcionalidade em um método de extensão ao longo das linhas de RemoveAll(this string s, params char[] toRemove)? A intenção será claramente comunicada e você não correrá o risco de digitar algo errado.
bzlm
12
@ Henk - A única razão pela qual uso string.Empty é porque acho que o objeto nulo fornecido por Empty expressa intenção melhor do que aspas vazias. As aspas vazias podem resultar de um problema de mesclagem, ou de um pensamento confuso, ou pode ser a intenção real desse código, enquanto Empty me diz explicitamente que o desenvolvedor pretendia que essa sequência não tivesse dados.
Ritch Melton
3
Há uma diferença entre "" e a string.Empty. Não que alguém se importe, realmente, mas "" cria um objeto, enquanto a string.Empty faz uso de um já feito. Mas, novamente, é tão pequeno, que situações única especiais que faria uma diferença
marcelo-ferraz
1
@ marcelo-ferrazm, sobre ""cria um objeto : Não, não.
Henk Holterman

Respostas:

272

Não existe um char vazio. O mais próximo que você pode chegar é '\0'o caractere "nulo" Unicode. Dado que você pode incorporar isso em literais de string ou expressá-lo por conta própria com muita facilidade, por que você deseja um campo separado para ele? Da mesma forma, os argumentos " é fácil confundir ""e " "" não se aplicam '\0'.

Se você pudesse dar um exemplo de onde você gostaria de usá-lo e por que você acha que seria melhor, isso pode ajudar ...

Jon Skeet
fonte
2
O \ 0 não é o caractere 'fim da matriz de bytes'? Ou estou confuso com outra coisa?
Bertvan
5
@ Bertvan: Por que haveria um caractere no final de uma matriz de bytes ? É usado para seqüências "terminadas em nulo", sim.
Jon Skeet
35
Char.MinValue é melhor que '\ 0'
Aliostad 08/09
10
@ Aliostad: Fora de interesse, se houvesse um campo semelhante para Int32.Zero, você usaria isso em vez do literal 0? Se não, qual é a diferença aqui?
Jon Skeet
7
@ Adam, @ Jon - qual é o código para a campainha? Ou retroceda melhor, pense, pense ... Ou talvez, em vez de pensar, seja melhor escrever Char.Backspace? Outro motivo - você diz que é melhor escrever '0' para o terminador; em vez disso, diga Char.Terminator, mas não é - é muito fácil fazer um erro de digitação (totalmente compilado, veja acima), mas tente escrever Char.Termnator. Existem razões suficientes para evitar valores brutos não verificáveis ​​(as missões espaciais falharam devido a erros estúpidos como esse).
greenoldman 9/09/10
87

Um char, diferente de uma string, é uma coisa discreta com um tamanho fixo. Uma string é realmente um contêiner de caracteres.

Portanto, Char.Empty realmente não faz sentido nesse contexto. Se você tem um char, ele não está vazio.

Joe
fonte
3
Exatamente certo. Faz sentido perguntar se um contêiner está vazio ou não. Não faz sentido pedir que um int, float ou char esteja vazio.
TED
1
@ Joe: Então, como uma string pode estar vazia se uma string é uma coleção de caracteres (não vazios)? Provavelmente estúpido, desculpe ...
user1477388
9
Como uma string não é um objeto individual, é uma coleção. Pense em um balde de pedras. Não posso ter uma pedra vazia. Mas eu posso ter um balde vazio.
Joe Joe
2
Eu o chamaria de "um caractere é um tipo de valor primitivo e uma string é um tipo de referência não primitivo".
Samis
3
Esta é a verdadeira resposta.
Gandalf458
31

Não existe um personagem vazio. Sempre contém algo . Mesmo '\ 0' é um personagem.

Philippe Leybaert
fonte
28

Use o Char.MinValueque funciona da mesma forma que '\ 0'. Mas tenha cuidado, não é o mesmo que String.Empty.

Aliostad
fonte
Obrigado, não vi isso antes. Você sabe se funciona em myString.Replace ('c', Char.MinValue)? Eu deveria tentar.
Joan Venge
19

Você pode usar caracteres anuláveis .

char? c
paquetp
fonte
Isso permite ''? Ou apenas nulo?
Joan Venge
No seu caso, você pode fazer isso: myString.Replace ("c", (c == null? "": C.ToString ()))
paquetp
12

Se você não precisar da string inteira, poderá tirar proveito da execução atrasada:

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

Você pode até combinar vários caracteres ...

string veryLongText = "abcdefghijk...";

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

... e apenas os 7 primeiros caracteres serão avaliados :)

EDIT: ou, melhor ainda:

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

e seu uso:

        var veryLongText = "abcdefghijk...";
        IEnumerable<char> firstFiveCharsWithoutCsAndDs = veryLongText
            .RemoveChars('c', 'd')
            .Take(5)
            .ToArray(); //to prevent multiple execution of "RemoveChars"
Notoriousxl
fonte
@Joan: obrigado ... mesmo que "Genius" é um pouco exagerado: P (eu não sei sobre seus desempenhos quando removingChars vai se tornar uma grande variedade ...)
Notoriousxl
1
Ontem eu esqueci: preste atenção em como você está usando a variável de resultado "firstFiveCharsWithoutCsAndDs". Se você não deseja passá-lo para outro método "yield" (como os do LINQ), chame imediatamente um ".ToArray ()" após o "Take (5)" ... caso contrário, o "RemoveChars + Take" A cadeia será executada toda vez que você acessar a variável de maneira "tradicional" (por exemplo, toda vez que você chamar "Count ()", ou quando você a percorrer em um foreach sem "retorno de rendimento")
Notoriousxl
+1 bom pensamento. mas isso não pode ficar tão sustentável ou eficiente como a abordagem básica :)
Nawfal
1
@nawfal em termos de eficiência, você está certo, mas acho que myString.Except ("c") é mais declarativo que myString.Replace ('c', ''): P (e ele escala muito bem: myString.Except ( "aeiou"))
Notoriousxl
7
myString = myString.Replace('c'.ToString(), "");

OK, isso não é particularmente elegante para remover letras, pois o método .Replace tem uma sobrecarga que aceita parâmetros de string. Mas isso funciona para remover retornos de carro, alimentações de linha, guias, etc. Este exemplo remove caracteres de tabulação:

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

a mesma razão que não existe int.Empty. Os recipientes podem estar vazios. Valores escalares não podem ser. Se você quer dizer 0 (que não está vazio), use '\0'. Se você quer dizer null, use null:)

dez quatro
fonte
2
null não é possível, pois char é um ValueType. Você teria que usar char? para poder atribuir nulo a ele.
Femaref
você deve torná-lo anulável. veja minha resposta
paquetp 08/09/10
5

Um caractere é um tipo de valor, portanto, seu valor não pode ser nulo. (A menos que esteja embrulhado em um recipiente Anulável).

Como não pode ser nulo, in contém algum código numérico e cada código é mapeado para algum caractere.

epotter
fonte
4

Não é uma resposta para sua pergunta, mas para indicar um padrão, charvocê pode usar apenas

default(char)

que é o mesmo char.MinValueque, por sua vez, é o mesmo que \0. Não se deve usar isso para algo como uma string vazia.

nawfal
fonte
1

Não responde sua primeira pergunta - mas, para o problema específico que você teve, você pode simplesmente usar strings em vez de caracteres, certo ?:

myString.Replace("c", "")

Existe uma razão para você não querer fazer isso?

Ian Grainger
fonte
1

Você também pode reconstruir sua sequência de caracteres por caractere, excluindo os caracteres dos quais deseja se livrar.

Aqui está um método de extensão para fazer isso:

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

Não é liso ou chique, mas funciona bem.

Use assim:

string newString = "My_String".RemoveAny("_"); //yields "MyString"
C. Tewalt
fonte
Use a StringBuilderpara result. Por que não embrulhar return s.Replace(charsToRemove,"");?
aloisdg movendo-se para codidact.com 09/07/16
1

Se você deseja remover caracteres que atendem a uma condição específica, você pode usar o seguinte:

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

(Isso deixará apenas os caracteres maiúsculos na string.)

Em outras palavras, você pode "usar" a string como uma IEnumerable<char>, fazer alterações e depois convertê-la novamente em uma string, como mostrado acima.

Novamente, isso permite não só remover um caractere específico por causa da expressão lambda, embora você pode fazer isso, se você alterar a expressão lambda assim: c => c != 't'.

florien
fonte
0

E quanto à BOM , o personagem mágico que a Microsoft adiciona ao início dos arquivos (pelo menos XML)?

Arto Viitanen
fonte
A redação na Wikipedia aqui é bastante infeliz; a lista técnica não é um personagem nesse contexto. E qual é a sua pergunta exatamente? :)
bzlm
@onemach, então, se myString.Replace ('c', '')poderia ser alcançado por myString.Replace ('c', UTF_BOM). Então eu diria que a resposta é "como não ...".
21412 bzlm
0

se você quiser eliminar o caractere vazio na string, o seguinte funcionará, apenas converta para qualquer representação de tipo de dados desejada. obrigado,

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
fonte
0

Em termos de linguagem C #, o seguinte pode não fazer muito sentido. E essa não é uma resposta direta à pergunta. Mas seguir é o que eu fiz em um dos meus cenários de negócios

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

O nulle white spaceteve diferentes fluxos de negócios no meu projeto. Ao inserir no banco de dados, preciso inseri empty string-lo no banco de dados, se houver espaço em branco.

LCJ
fonte
0

Sei que este é bastante antigo, mas recentemente encontrei um problema ao fazer várias substituições para tornar um nome de arquivo seguro. Primeiro, na string .NET mais recente. A função null é equivalente a um caractere vazio. Dito isto, o que está faltando no .Net é uma simples substituição de tudo o que substituirá qualquer caractere em uma matriz pelo caractere desejado. Por favor, sinta-se à vontade para referenciar o código abaixo (executado no LinqPad para teste).

// 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
fonte
-3

usar

myString.Replace ("c", "")
Chintan
fonte
2
Esta é uma duplicata da resposta de 2013 por Ian Grainger.
Joe Gayetty
-3

A maneira mais fácil de remover um caractere da string é cortá-lo

cl = cl.Trim(' ');

Remove todos os espaços em uma sequência

MrSmudge
fonte
Isso é útil se alguém quiser usar o uso. Substitua ('c', '') pela desvantagem de remover outros espaços em branco. Mas é mais útil do que muitas outras respostas dadas.
Jan
1
Não, isso está errado! Única guarnição remover caracteres desde o início e final de uma string não no meio
userSteve