BestPractice - преобразовать первый символ строки в нижний регистр


136

Я хотел бы иметь метод, который преобразует первый символ строки в нижний регистр.

Мои подходы:

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

Каков будет ваш подход?

Ответы:


240

Я бы использовал простую конкатенацию:

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

Первое решение не оптимизировано, потому что string.Formatоно медленное, и оно вам не нужно, если у вас есть формат, который никогда не изменится. Он также генерирует дополнительную строку для преобразования буквы в нижний регистр, которая не нужна.

Подход с «+ 32» является уродливым / не обслуживаемым, поскольку требует знания смещений значений символов ASCII. Он также будет генерировать неправильный вывод с данными Unicode и символьными символами ASCII.


4
я бы сделал это:char.ToLower(name[0]).ToString() + name.Substring(1)
Андрей

7
@Rookian: +оператор работает медленно, когда вы объединяете много строк. В этом случае он StringBuilderбудет работать намного лучше. Тем не менее, +это гораздо быстрее, чем string.Format. Используйте последнее, когда вам действительно нужно что-то отформатировать (например, отображать целые числа, двойные числа или даты).
Дирк Воллмар

6
@ 0x03: это только медленно, если вы объединяете много строк итеративно. Если вы объединяете их все в одну операцию, +оператор вообще не работает медленно, потому что компилятор превращает его в String.Concat(но String.Joinэто быстрее, чем String.Concatпо какой-то глупой причине).
Торарин

2
Более быстрый метод: публичная статическая строка ToFirstLetterLower (текст строки) {var charArray = text.ToCharArray (); charArray [0] = char.ToLower (charArray [0]); вернуть новую строку (charArray); }
Маттео Мильоре

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); } на основе комментария @ MatteoMigliore.
KregHEk

64

В зависимости от ситуации может потребоваться небольшое защитное программирование:

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

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

Этот ifоператор также предотвращает создание новой строки, если она все равно не будет изменена. Возможно, вы захотите, чтобы метод потерпел неудачу на нулевом вводе, и бросил ArgumentNullException.

Как уже упоминалось, использование String.Formatдля этого является излишним.


Поправьте меня, если я ошибаюсь, но str.Substring (1) вернет символ в позиции 1, так как счетчик для этого метода не указан. поэтому у вас будет символ [0] в нижнем регистре + символ в позиции 1. Поэтому я предпочел удалить один символ, начиная с первого символа в строке. Результатом является строка без первой буквы. Затем я добавлю эту строку в первый символ, который преобразуется в нижний регистр
fedotoves

3
@ B-Rain: считать себя исправил: msdn.microsoft.com/en-us/library/hxthx5h6%28VS.90%29.aspx
Торарин

7

На всякий случай это поможет любому, кто случайно наткнется на этот ответ.

Я думаю, что это будет лучше в качестве метода расширения, тогда вы можете вызвать его с помощью 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);
    }
}

3

Мой

if (!string.IsNullOrEmpty (val) && val.Length > 0)
{
    return val[0].ToString().ToLowerInvariant() + val.Remove (0,1);   
}

3
Мне любопытно, почему val.Remove? Кажется, немного нелогичным для меня.
Торарин

@Thorarin, очевидно, потому что вы хотите удалить первый символ (потому что вы добавляете
Riki

2

Мне нравится принятый ответ, но помимо проверки string.IsNullOrEmptyя бы также проверил, если Char.IsLower(name[1])вы имеете дело с сокращением. Например, вы не хотели бы, чтобы «СПИД» стал «СПИДом».


8
ИМО это ответственность вызывающего
onof

1

Самое быстрое решение, которое я знаю, не злоупотребляя 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;
}

0

Объединили несколько и сделали его цепным расширением. Добавлено короткое замыкание на пробел и не букву.

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;

0

Это небольшой метод расширения, использующий последний синтаксис и правильные проверки

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

1
Не уверен, что выбрасывание исключения будет лучшим решением. Если строка пуста или пуста, просто верните пустую или пустую строку.
Р. де Вин,

Если String равен нулю или пуст, операция не имеет смысла, так как нет первого символа, который можно изменить на строчные.
Карлос Муньос,


-3

Лучше использовать, String.Concatчем String.Formatесли вы знаете, что формат не изменяет данные, а просто объединение желательно.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.