BestPractice: transforma el primer carácter de una cadena en minúsculas

136

Me gustaría tener un método que transforme el primer carácter de una cadena en minúsculas.

Mis enfoques:

1)

public static string ReplaceFirstCharacterToLowerVariant(string name)
{
    return String.Format("{0}{1}", name.First().ToString().ToLowerInvariant(), name.Substring(1));
}

2)

public static IEnumerable<char> FirstLetterToLowerCase(string value)
{
    var firstChar = (byte)value.First();
    return string.Format("{0}{1}", (char)(firstChar + 32), value.Substring(1));
}

¿Cuál sería tu enfoque?

Rookiano
fuente

Respuestas:

240

Yo usaría una concatenación simple:

Char.ToLowerInvariant(name[0]) + name.Substring(1)

La primera solución no está optimizada porque string.Format es lenta y no la necesita si tiene un formato que nunca cambiará. También genera una cadena adicional para convertir la letra a minúsculas, lo cual no es necesario.

El enfoque con "+ 32" es feo / no se puede mantener, ya que requiere el conocimiento de las compensaciones de valores de caracteres ASCII. También generará resultados incorrectos con datos Unicode y caracteres de símbolos ASCII.

onof
fuente
44
lo haría:char.ToLower(name[0]).ToString() + name.Substring(1)
Andrey
77
@Rookian: el +operador es lento cuando concatena muchas cadenas. En ese caso StringBuilder, a funcionaría mucho mejor. Sin embargo, +es mucho más rápido que string.Format. Use este último cuando realmente necesite formatear algo (como mostrar enteros, dobles o fechas).
Dirk Vollmar
66
@ 0x03: solo es lento si concatena muchas cadenas de forma iterativa. Si los concatena todos en una sola operación, el +operador no es lento en absoluto, porque el compilador lo convierte en un String.Concat(sin embargo, String.Joines más rápido que String.Concatpor alguna razón tonta).
Thorarin
2
Un método más rápido es este: cadena estática pública ToFirstLetterLower (texto de cadena) {var charArray = text.ToCharArray (); charArray [0] = char.ToLower (charArray [0]); devolver nueva cadena (charArray); }
Matteo Migliore
2
public static string ToLowerFirst(this string source) { if (string.IsNullOrWhiteSpace(source)) return source; var charArray = source.ToCharArray(); charArray[0] = char.ToLower(charArray[0]); return new string(charArray); } Usé la extensión Basado en el comentario de @ MatteoMigliore.
KregHEk
64

Dependiendo de la situación, una pequeña programación defensiva podría ser deseable:

public static string FirstCharacterToLower(string str)
{
    if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0))
        return str;

    return Char.ToLowerInvariant(str[0]) + str.Substring(1);
}

La ifdeclaración también evita que se cree una nueva cadena si no se va a cambiar de todos modos. Es posible que desee que el método falle en la entrada nula y arroje un ArgumentNullException.

Como la gente ha mencionado, usar String.Formatpara esto es exagerado.

Thorarin
fuente
Corrígeme si estoy equivocado pero str.Substring (1) devolverá el símbolo en la posición 1 ya que el recuento de este método no está indicado. entonces tendrá char [0] en minúsculas + el carácter en la posición 1 Así que preferí eliminar un carácter a partir del primer carácter en la cadena. El resultado es la cadena sin primera letra. Luego
agregaré
3
@ B-Rain: considérese corregido: msdn.microsoft.com/en-us/library/hxthx5h6%28VS.90%29.aspx
Thorarin
7

Por si acaso, ayuda a cualquiera que tropiece con esta respuesta.

Creo que esto sería mejor como método de extensión, entonces puede llamarlo con yourString.FirstCharacterToLower ();

public static class StringExtensions
{
    public static string FirstCharacterToLower(this string str)
    {
        if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0))
        {
            return str;
        }

        return Char.ToLowerInvariant(str[0]) + str.Substring(1);
    }
}
carlcheel
fuente
3

El mio es

if (!string.IsNullOrEmpty (val) && val.Length > 0)
{
    return val[0].ToString().ToLowerInvariant() + val.Remove (0,1);   
}
Fedotoves
fuente
3
Tengo curiosidad, ¿por qué val.Remove? Me parece un poco intuitivo.
Thorarin
@Thorarin obviamente porque desea eliminar el primer carácter (porque está agregando la versión en minúscula al frente)
Riki
2

Me gusta la respuesta aceptada, pero además de verificar string.IsNullOrEmptytambién verificaría si Char.IsLower(name[1])se trata de abreviaturas. Por ejemplo, no querrá que el "SIDA" se convierta en "SIDA".

Slobodan Savkovic
fuente
8
OMI esto es responsabilidad de la persona que llama
onof
1

La solución más rápida que conozco sin abusar de C #:

public static string LowerCaseFirstLetter(string value)
{
    if (value?.Length > 0)
    {
        var letters = value.ToCharArray();
        letters[0] = char.ToLowerInvariant(letters[0]);
        return new string(letters);
    }
    return value;
}
Rjz
fuente
0

Combinó algunos y lo convirtió en una extensión encadenable. Cortocircuito agregado en espacios en blanco y sin letras.

public static string FirstLower(this string input) => 
    (!string.IsNullOrWhiteSpace(input) && input.Length > 0 
        && char.IsLetter(input[0]) && !char.IsLower(input[0]))
    ? input[0].ToString().ToLowerInvariant() + input.Remove(0, 1) : input;
Randy Buchholz
fuente
0

Este es un pequeño método de extensión que utiliza la sintaxis más reciente y las validaciones correctas

public static class StringExtensions
{
    public static string FirstCharToLower(this string input)
    {
        switch (input)
        {
            case null: throw new ArgumentNullException(nameof(input));
            case "": throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input));
            default: return input.First().ToString().ToLower() + input.Substring(1);
        }
    }
}
Carlos Muñoz
fuente
1
No estoy seguro si lanzar una excepción sería la mejor solución. Si la cadena es nula o vacía, solo devuelve la cadena nula o vacía.
R. de Veen
Si String es nulo o está vacío, la operación no tiene sentido ya que no hay un primer carácter para cambiar a minúsculas.
Carlos Muñoz
0

Utilizar este:

string newName= name[0].ToString().ToLower() + name.Substring(1);
hojjat.mi
fuente
-3

Es mejor usar String.Concatque String.Formatsi sabe que el formato no es cambiar datos, y solo se desea la concatenación.

Konstantin Isaev
fuente