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.