我有一个带有文本框的DetailsView
我希望输入的数据总是以大写的第一个字母保存。
例子:
"red" --> "Red"
"red house" --> " Red house"
我怎样才能实现性能最大化呢?
注意:
Based on the answers and the comments under the answers, many people think this is asking about capitalizing all words in the string. E.g. => Red House It isn't, but if that is what you seek, look for one of the answers that uses TextInfo's ToTitleCase method. (Note: Those answers are incorrect for the question actually asked.)
See TextInfo.ToTitleCase documentation for caveats (doesn't touch all-caps words - they are considered acronyms; may lowercase letters in middle of words that "shouldn't" be lowered, e.g., "McDonald" → "Mcdonald"; not guaranteed to handle all culture-specific subtleties re capitalization rules.)
注意:
第一个字母之后的字母是否必须小写,这个问题很模糊。公认的答案假定只有第一个字母需要修改。如果要强制字符串中除第一个字母外的所有字母都小写,请查找包含ToLower且不包含ToTitleCase的答案。
这里有一个方法来做它作为一个扩展方法:
static public string UpperCaseFirstCharacter(this string text)
{
if (!string.IsNullOrEmpty(text))
{
return string.Format(
"{0}{1}",
text.Substring(0, 1).ToUpper(),
text.Substring(1));
}
return text;
}
然后可以像这样调用它:
//yields "This is Brian's test.":
"this is Brian's test.".UpperCaseFirstCharacter();
下面是一些单元测试:
[Test]
public void UpperCaseFirstCharacter_ZeroLength_ReturnsOriginal()
{
string orig = "";
string result = orig.UpperCaseFirstCharacter();
Assert.AreEqual(orig, result);
}
[Test]
public void UpperCaseFirstCharacter_SingleCharacter_ReturnsCapital()
{
string orig = "c";
string result = orig.UpperCaseFirstCharacter();
Assert.AreEqual("C", result);
}
[Test]
public void UpperCaseFirstCharacter_StandardInput_CapitalizeOnlyFirstLetter()
{
string orig = "this is Brian's test.";
string result = orig.UpperCaseFirstCharacter();
Assert.AreEqual("This is Brian's test.", result);
}
由于这个问题是关于最大化性能的,我采用了Darren的版本来使用跨度,这减少了垃圾,并提高了大约10%的速度。
/// <summary>
/// Returns the input string with the first character converted to uppercase
/// </summary>
public static string ToUpperFirst(this string s)
{
if (string.IsNullOrEmpty(s))
throw new ArgumentException("There is no first letter");
Span<char> a = stackalloc char[s.Length];
s.AsSpan(1).CopyTo(a.Slice(1));
a[0] = char.ToUpper(s[0]);
return new string(a);
}
性能
Method |
Data |
Mean |
Error |
StdDev |
Carlos |
red |
107.29 ns |
2.2401 ns |
3.9234 ns |
Darren |
red |
30.93 ns |
0.9228 ns |
0.8632 ns |
Marcell |
red |
26.99 ns |
0.3902 ns |
0.3459 ns |
Carlos |
red house |
106.78 ns |
1.9713 ns |
1.8439 ns |
Darren |
red house |
32.49 ns |
0.4253 ns |
0.3978 ns |
Marcell |
red house |
27.37 ns |
0.3888 ns |
0.3637 ns |
完整的测试代码
using System;
using System.Linq;
using BenchmarkDotNet.Attributes;
namespace CorePerformanceTest
{
public class StringUpperTest
{
[Params("red", "red house")]
public string Data;
[Benchmark]
public string Carlos() => Data.Carlos();
[Benchmark]
public string Darren() => Data.Darren();
[Benchmark]
public string Marcell() => Data.Marcell();
}
internal static class StringExtensions
{
public static string Carlos(this string input) =>
input switch
{
null => throw new ArgumentNullException(nameof(input)),
"" => throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)),
_ => input.First().ToString().ToUpper() + input.Substring(1)
};
public static string Darren(this string s)
{
if (string.IsNullOrEmpty(s))
throw new ArgumentException("There is no first letter");
char[] a = s.ToCharArray();
a[0] = char.ToUpper(a[0]);
return new string(a);
}
public static string Marcell(this string s)
{
if (string.IsNullOrEmpty(s))
throw new ArgumentException("There is no first letter");
Span<char> a = stackalloc char[s.Length];
s.AsSpan(1).CopyTo(a.Slice(1));
a[0] = char.ToUpper(s[0]);
return new string(a);
}
}
}