将字符串的第一个字符转换为小写

我希望有一个方法可以将字符串的第一个字符转换为小写。

我的方法是:

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

你的方法是什么?

65623 次浏览

我会使用简单的连接:

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

第一个解决方案是没有优化,因为 string.Format是缓慢的,你不需要它,如果你有一个格式,永远不会改变。它还生成一个额外的字符串来将字母转换为小写,这是不需要的。

使用“ + 32”的方法很难看/不可维护,因为它需要了解 ASCII 字符值偏移量。它还将使用 Unicode 数据和 ASCII 符号字符生成不正确的输出。

我的才是

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

根据具体情况,一点防御性编程可能是可取的:

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做这件事是过分的。

我喜欢接受的答案,但除了检查 string.IsNullOrEmpty我也会检查如果 Char.IsLower(name[1])的情况下,你是处理缩写。例如,你不会希望“艾滋病”变成“艾滋病”。

如果您知道格式不是更改数据,并且只需要连接,那么使用 String.Concat比使用 String.Format更好。

以防有人碰巧找到这个答案。

我认为这最好作为一个扩展方法,然后您可以使用 yourString 调用它

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

结合了一些,使它成为一个可链接的扩展。增加了空格和非字母短路。

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;

这是一个使用最新语法和正确验证的小型扩展方法

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

使用方法:

string newName= name[0].ToString().ToLower() + name.Substring(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;
}

如果不想在表达式中引用字符串两次,可以使用 System.Linq来实现。

new string("Hello World".Select((c, i) => i == 0 ? char.ToLower(c) : c).ToArray())

这样,如果字符串来自一个函数,就不必存储该函数的结果。

new string(Console.ReadLine().Select((c, i) => i == 0 ? char.ToLower(c) : c).ToArray())

如果你在乎表现的话,我会选

  public static string FirstCharToLower(this string str)
=> string.Create(str.Length, str, (output, input) =>
{
input.CopyTo(output);
output[0] = char.ToLowerInvariant(input[0]);
});

我做了一些快速的基准测试,它似乎至少是两倍的速度,最快的解决方案张贴在这里,3.5倍的速度比最差的一个在多个输入长度。

没有输入检查,因为它应该是调用者的责任。允许您提前准备数据并进行快速批量处理,如果需要的话,不会因为在热路径中设置分支而减慢速度。

使用 C # 8.0或更高版本,你可以这样做:

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