¿Por qué no hay Char.Empty como String.Empty?

259

¿Hay alguna razón para esto? Le pregunto porque si necesita usar muchos caracteres vacíos, entonces se encuentra en la misma situación que cuando usa muchas cadenas vacías.

Editar: El motivo de este uso fue este:

myString.Replace ('c', '')

Entonces, elimine todas las instancias de 'c's de myString.

Joan Venge
fuente
1
Sí, usé esa palabra por falta de una palabra mejor. es decir, la forma recomendada de usar String.Empty en lugar de "".
Joan Venge
3
Si a veces le preocupa escribir mal '' accidentalmente, ¿por qué no simplemente envolver la funcionalidad en un método de extensión en la línea de RemoveAll(this string s, params char[] toRemove)? La intención se comunicará claramente y no se arriesgará a escribir mal.
bzlm
12
@Henk: la única razón por la que uso string.Empty es porque encuentro que el objeto nulo proporcionado por Empty expresa la intención mejor que las comillas vacías. Las comillas vacías podrían ser el resultado de un problema de fusión, o un pensamiento confuso, o podría ser la intención real de ese código, mientras que Empty explícitamente me dice que el desarrollador pretendía que esa cadena no tuviera datos.
Ritch Melton
3
Hay una diferencia entre "" y la cadena. Vacío. No es que a nadie le importe, en realidad, pero "" crea un objeto, mientras que string.Empty utiliza uno que ya está hecho. Pero, de nuevo, es tan pequeño, que solo situaciones especiales marcarían la diferencia
marcelo-ferraz
1
@ marcelo-ferrazm, acerca de ""crea un objeto : No, no lo hace.
Henk Holterman

Respuestas:

272

No hay tal cosa como un carbón vacío. Lo más cercano que puede obtener es '\0'el carácter "nulo" de Unicode. Dado que puede incrustar eso dentro de los literales de cadena o expresarlo por sí solo muy fácilmente, ¿por qué querría un campo separado para él? Igualmente, los argumentos de " es fácil confundir ""y " "" no se aplican '\0'.

Si pudiera dar un ejemplo de dónde desea usarlo y por qué cree que sería mejor, eso podría ayudar ...

Jon Skeet
fuente
2
¿No es el \ 0 el carácter 'final de la matriz de bytes'? ¿O estoy confundiendo con algo más?
Bertvan
55
@Bertvan: ¿Por qué habría un carácter al final de una matriz de bytes ? Sin embargo, se usa para cadenas "terminadas en nulo", sí.
Jon Skeet
35
Char.MinValue es mejor que '\ 0'
Aliostad
10
@Aliostad: Fuera de interés, si hubiera un campo similar para Int32.Zero, ¿lo usarías en lugar del 0 literal? Si no, ¿cuál es la diferencia aquí?
Jon Skeet
77
@Adam, @Jon: ¿cuál es el código de Bell? O retrocede mejor, piensa piensa ... O tal vez en lugar de pensar que es mejor escribir Char.Backspace? Otra razón: usted dice que es mejor escribir '0' para el terminador, en cambio, diga Char.Terminator, pero no lo es: es demasiado fácil hacer un error tipográfico (completamente compilado, ver arriba), pero intente escribir Char.Termnator. Hay suficientes razones para evitar valores no verificables en bruto (las misiones espaciales fallaron debido a errores estúpidos como ese).
greenoldman
87

Un char, a diferencia de una cadena, es algo discreto con un tamaño fijo. Una cadena es realmente un contenedor de caracteres.

Entonces, Char.Empty realmente no tiene sentido en ese contexto. Si tienes un carbón, no está vacío.

Joe
fuente
3
Exactamente correcto. Tiene sentido preguntar si un contenedor está vacío o no. No tiene sentido pedirle a int o float o char que esté vacío.
TED
1
@ Joe: Entonces, ¿cómo puede una cadena estar vacía si una cadena es una colección de caracteres (no vacíos)? Probablemente estúpido, lo siento ...
user1477388
9
Debido a que una cadena no son los objetos individuales, es la colección. Piensa en un cubo de rocas. No puedo tener una roca vacía. Pero puedo tener un cubo vacío.
Joe
2
Lo diría como "un carácter es un tipo de valor primitivo y una cadena es un tipo de referencia no primitivo".
samis
3
Esta es la verdadera respuesta.
Gandalf458
31

No existe un personaje vacío. Siempre contiene algo . Incluso '\ 0' es un personaje.

Philippe Leybaert
fuente
28

Utilice el Char.MinValueque funciona igual que '\ 0'. Pero ten cuidado, no es lo mismo que String.Empty.

Aliostad
fuente
Gracias, no he visto eso antes. ¿Sabes si funciona en myString.Replace ('c', Char.MinValue)? Debería intentarlo.
Joan Venge
19

Podrías usar caracteres anulables .

char? c
paquetp
fuente
Esto permite ''? O simplemente nulo?
Joan Venge
En su caso, puede hacer esto: myString.Replace ("c", (c == null? "": C.ToString ()))
paquetp
12

Si no necesita la cadena completa, puede aprovechar la ejecución retrasada:

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

Incluso puedes combinar varios personajes ...

string veryLongText = "abcdefghijk...";

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

... y solo se evaluarán los primeros 7 caracteres :)

EDITAR: o, mejor aún:

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

y su uso:

        var veryLongText = "abcdefghijk...";
        IEnumerable<char> firstFiveCharsWithoutCsAndDs = veryLongText
            .RemoveChars('c', 'd')
            .Take(5)
            .ToArray(); //to prevent multiple execution of "RemoveChars"
Notorio xl
fuente
@Joan: gracias ... incluso si "Genius" es un poco exagerado: P (no sé acerca de su rendimiento cuando eliminar Chars se convertirá en una gran variedad ...)
Notoriousxl
1
Ayer se me olvidó: preste atención a cómo está utilizando la variable de resultado "firstFiveCharsWithoutCsAndDs". Si no desea pasarlo a otro método de "rendimiento" (como los de LINQ), llame inmediatamente a ".ToArray ()" después de "Take (5)" ... de lo contrario, "RemoveChars + Take" la cadena se ejecutará cada vez que acceda a la variable de forma "tradicional" (por ejemplo, cada vez que llame a "Count ()" en ella, o cuando la atraviese en un foreach sin "retorno de rendimiento")
Notoriousxl
+1 buen pensamiento. pero esto no puede ser tan
fácil de
1
@nawfal en cuanto a eficiencia, tiene razón, pero creo que myString.Except ("c") es más declarativo que myString.Replace ('c', ''): P (y se escala bastante bien: myString.Except ( "aeiou"))
Notoriousxl
7
myString = myString.Replace('c'.ToString(), "");

OK, esto no es particularmente elegante para eliminar letras, ya que el método .Replace tiene una sobrecarga que toma parámetros de cadena. Pero esto funciona para eliminar retornos de carro, saltos de línea, pestañas, etc. Este ejemplo elimina los caracteres de tabulación:

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

la misma razón por la que no hay un int.Empty. Los contenedores pueden estar vacíos. Los valores escalares no pueden ser. Si quiere decir 0 (que no está vacío), use '\0'. Si quieres decir null, entonces usa null:)

diez cuatro
fuente
2
nulo no es posible ya que char es un ValueType. ¿Tendrías que usar char? para poder asignarle nulo.
Femaref
Podrías hacerlo anulable. mira mi respuesta
paquetp
5

Un carácter es un tipo de valor, por lo que su valor no puede ser nulo. (A menos que esté envuelto en un contenedor Nullable).

Como no puede ser nulo, contiene un código numérico y cada código se asigna a algún carácter.

epotter
fuente
4

No es una respuesta a su pregunta, pero para denotar un valor predeterminado char, puede usar solo

default(char)

que es lo mismo char.MinValueque a su vez es lo mismo que \0. Sin embargo, no se debe usar para algo como una cadena vacía.

nawfal
fuente
1

No responde su primera pregunta, pero para el problema específico que tuvo, puede usar cadenas en lugar de caracteres, ¿verdad ?:

myString.Replace("c", "")

¿Hay alguna razón por la que no quieras hacer eso?

Ian Grainger
fuente
1

También puede reconstruir su cadena carácter por carácter, excluyendo los caracteres de los que desea deshacerse.

Aquí hay un método de extensión para hacer esto:

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

No es elegante ni elegante, pero funciona bien.

Usar así:

string newString = "My_String".RemoveAny("_"); //yields "MyString"
C. Tewalt
fuente
Use un StringBuilderpara result. ¿Por qué no envolver return s.Replace(charsToRemove,"");?
aloisdg se muda a codidact.com
1

Si desea eliminar caracteres que satisfacen una condición específica, puede usar esto:

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

(Esto dejará solo los caracteres en mayúscula en la cadena).

En otras palabras, puede "usar" la cadena como un IEnumerable<char> , hacer cambios en ella y luego convertirla nuevamente a una cadena como se muestra arriba.

De nuevo, esto permite no sólo eliminar un caracter específico debido a la expresión lambda, aunque puede hacerlo si cambia la expresión lambda como esto: c => c != 't'.

florien
fuente
0

¿Qué tal BOM , el personaje mágico que Microsoft agrega al inicio de los archivos (al menos XML)?

Arto Viitanen
fuente
La redacción en Wikipedia aquí es bastante desafortunada; La lista de materiales no es un personaje en este contexto. ¿Y cuál es tu pregunta exactamente? :)
bzlm
@onemach, entonces, si myString.Replace ('c', '')podría lograrse mediante myString.Replace ('c', UTF_BOM). Entonces diría que la respuesta es "¿cómo no se trata de ...".
bzlm
0

si desea eliminar el carácter vacío en la cadena, lo siguiente funcionará, simplemente conviértalo a cualquier representación de tipo de datos que desee. Gracias,

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

En términos de lenguaje C #, lo siguiente puede no tener mucho sentido. Y esta no es una respuesta directa a la pregunta. Pero fowlloing es lo que hice en uno de mis escenarios comerciales

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

El nully white spacetenía diferentes flujos de negocios en mi proyecto. Al insertar en la base de datos, necesito insertar empty stringen la base de datos si es un espacio en blanco.

LCJ
fuente
0

Sé que este es bastante viejo, pero recientemente encontré un problema con tener que hacer múltiples reemplazos para que un nombre de archivo sea seguro. Primero, en la última cadena .NET. La función de reemplazo nulo es el equivalente al carácter vacío. Dicho esto, lo que falta en .Net es un simple reemplazo de todo lo que reemplazará cualquier carácter en una matriz con el carácter deseado. No dude en consultar el código a continuación (se ejecuta en LinqPad para realizar pruebas).

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

utilizar

myString.Replace ("c", "")
Chintan
fuente
2
Este es un duplicado de una respuesta de 2013 de Ian Grainger.
Joe Gayetty
-3

La forma más fácil de eliminar un personaje de una cadena es recortarlo

cl = cl.Trim(' ');

Elimina todos los espacios en una cadena

MrSmudge
fuente
Esto es útil si se quiere usar el uso .Replace ('c', '') con la desventaja de eliminar otros espacios en blanco. Pero es más útil que muchas otras respuestas dadas.
Ene
1
No, esto está mal! Recortar solo elimina caracteres del principio y el final de una cadena que no esté en el medio
userSteve