我有一个带有 TextBox
的 DetailsView
,我希望 输入数据始终保存,并使用 首字母大写 。
例子:
"red" --> "Red"
"red house" --> " Red house"
我怎样才能实现这种最大化的性能?
笔记:
根据答案和答案下的评论,许多人认为这是在询问字符串中的 all 单词是否大写。例如 => Red House
不是,但如果这是您所寻求的,请寻找使用 TextInfo
的 ToTitleCase
方法的答案之一。 (注意:对于实际提出的问题,这些答案不正确。)请参阅 TextInfo.ToTitleCase documentation 以了解警告(不涉及全大写单词 - 它们被视为首字母缩略词;可能会在单词中间出现小写字母“不应该”被降低,例如,“McDonald”→“Mcdonald”;不保证能处理所有特定文化的细微差别重新大写规则。)
笔记:
关于第一个字母之后的字母是否应该强制小写,问题是不明确。接受的答案假定只应更改第一个字母。如果您想强制字符串中除第一个以外的所有字母为小写,请查找包含 ToLower
且不包含 ToTitleCase 的答案。
不同C#版本的解决方案
至少具有 .NET Core 3.0 或 .NET Standard 2.1 的 C# 8
public static class StringExtensions
{
public static string FirstCharToUpper(this string input) =>
input switch
{
null => throw new ArgumentNullException(nameof(input)),
"" => throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)),
_ => string.Concat(input[0].ToString().ToUpper(), input.AsSpan(1))
};
}
由于 .NET Core 3.0 / .NET Standard 2.1 String.Concat()
支持 ReadonlySpan<char>
,如果我们使用 .AsSpan(1)
而不是 .Substring(1)
,则可以节省一次分配。
C# 8
public static class StringExtensions
{
public static string FirstCharToUpper(this string input) =>
input switch
{
null => throw new ArgumentNullException(nameof(input)),
"" => throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)),
_ => input[0].ToString().ToUpper() + input.Substring(1)
};
}
C# 7
public static class StringExtensions
{
public static string FirstCharToUpper(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[0].ToString().ToUpper() + input.Substring(1);
}
}
}
真的很老的答案
public static string FirstCharToUpper(string input)
{
if (String.IsNullOrEmpty(input))
throw new ArgumentException("ARGH!");
return input.First().ToString().ToUpper() + String.Join("", input.Skip(1));
}
这个版本较短。如需更快的解决方案,请查看 Diego's answer。
public static string FirstCharToUpper(string input)
{
if (String.IsNullOrEmpty(input))
throw new ArgumentException("ARGH!");
return input.First().ToString().ToUpper() + input.Substring(1);
}
最快的解决方案可能是 Darren's(甚至还有一个基准),尽管我会更改它的 string.IsNullOrEmpty(s)
验证以引发异常,因为最初的要求期望第一个字母存在,因此它可以大写。请注意,此代码适用于通用字符串,而不适用于 Textbox
中的有效值。
public string FirstLetterToUpper(string str)
{
if (str == null)
return null;
if (str.Length > 1)
return char.ToUpper(str[0]) + str.Substring(1);
return str.ToUpper();
}
旧答案:这使得每个第一个字母都大写
public string ToTitleCase(string str)
{
return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str.ToLower());
}
正确的方法是使用文化:
System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(word.ToLower())
注意:这会将字符串中的每个单词大写,例如“red house”->“Red House”。该解决方案还将单词中的小写字母大写,例如“old McDonald” --> “Old Mcdonald”。
ToLower
是错误的,因为它消除了单词中间的大写字母,例如“McDonalds”。 3) 问题是关于只改变字符串的第一个单词,不是关于TitleCase。
我从 C# Uppercase First Letter - Dot Net Perls 中采用了最快的方法并转换为扩展方法:
/// <summary>
/// Returns the input string with the first character converted to uppercase, or mutates any nulls passed into string.Empty
/// </summary>
public static string FirstLetterToUpperCaseOrConvertNullToEmptyString(this string s)
{
if (string.IsNullOrEmpty(s))
return string.Empty;
char[] a = s.ToCharArray();
a[0] = char.ToUpper(a[0]);
return new string(a);
}
注意:使用 ToCharArray
比替代 char.ToUpper(s[0]) + s.Substring(1)
更快的原因是只分配了一个字符串,而 Substring
方法为子字符串分配了一个字符串,然后是第二个字符串来组成最终结果。
结合来自 CarlosMuñoz's accepted answer 的初始测试,此方法如下所示:
/// <summary>
/// Returns the input string with the first character converted to uppercase
/// </summary>
public static string FirstLetterToUpperCase(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);
}
char.ToUpperInvariant
甚至快 20%
您可以使用“ToTitleCase 方法”:
string s = new CultureInfo("en-US").TextInfo.ToTitleCase("red house");
//result : Red House
这种扩展方法解决了每个标题问题。
它很容易使用:
string str = "red house";
str.ToTitleCase();
//result : Red house
string str = "red house";
str.ToTitleCase(TitleCase.All);
//result : Red House
扩展方法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
namespace Test
{
public static class StringHelper
{
private static CultureInfo ci = new CultureInfo("en-US");
//Convert all first latter
public static string ToTitleCase(this string str)
{
str = str.ToLower();
var strArray = str.Split(' ');
if (strArray.Length > 1)
{
strArray[0] = ci.TextInfo.ToTitleCase(strArray[0]);
return string.Join(" ", strArray);
}
return ci.TextInfo.ToTitleCase(str);
}
public static string ToTitleCase(this string str, TitleCase tcase)
{
str = str.ToLower();
switch (tcase)
{
case TitleCase.First:
var strArray = str.Split(' ');
if (strArray.Length > 1)
{
strArray[0] = ci.TextInfo.ToTitleCase(strArray[0]);
return string.Join(" ", strArray);
}
break;
case TitleCase.All:
return ci.TextInfo.ToTitleCase(str);
default:
break;
}
return ci.TextInfo.ToTitleCase(str);
}
}
public enum TitleCase
{
First,
All
}
}
FirstLetterToUpper
在 Equiso 的答案中(或在 Guillernet 的较新答案中)和 ToTitleCase
在此处,但没有第二个参数。那么不需要enum TitleCase
。
对于第一个字母,带有错误检查:
public string CapitalizeFirstLetter(string s)
{
if (String.IsNullOrEmpty(s))
return s;
if (s.Length == 1)
return s.ToUpper();
return s.Remove(1).ToUpper() + s.Substring(1);
}
这与方便的扩展相同
public static string CapitalizeFirstLetter(this string s)
{
if (String.IsNullOrEmpty(s))
return s;
if (s.Length == 1)
return s.ToUpper();
return s.Remove(1).ToUpper() + s.Substring(1);
}
public static string ToInvarianTitleCase(this string self)
{
if (string.IsNullOrWhiteSpace(self))
{
return self;
}
return CultureInfo.InvariantCulture.TextInfo.ToTitleCase(self);
}
在我们的方法中使用 string.Create() 并避免使用 throw
关键字(是的,您没看错),我们可以将 Marcell's answer 更进一步。此外,我的方法处理任意长度的字符串(例如,几兆字节的文本)。
public static string L33t(this string s)
{
static void ThrowError() => throw new ArgumentException("There is no first letter");
if (string.IsNullOrEmpty(s))
ThrowError(); // No "throw" keyword to avoid costly IL
return string.Create(s.Length, s, (chars, state) =>
{
state.AsSpan().CopyTo(chars); // No slicing to save some CPU cycles
chars[0] = char.ToUpper(chars[0]);
});
}
表现
以下是在 .NET Core 3.1.7、64 位上运行的基准测试的数字。我添加了一个更长的字符串来确定额外副本的成本。
方法数据平均错误stddev中值L33T红色8.545 NS 0.4612 NS 1.3308 NS 8.075 NS MARCELL RED 9.153 NS 0.3377 NS 0.9471 NS 0.946 NS 8.946 NS 8.946 NS NS NS L33T L33T RED HOUSE 7.715 NS 0.1741 NS 0.1741 NS 0.461 NS NES 7.463 NS RED MARC RED RED MARC RED RED RED RED RED MARC RED RED RED MARC RED RED RED MARC RED RED RED MARC RED REL r(...)house [89] 11.121 ns 0.6774 ns 1.9106 ns 10.612 ns Marcell 红 r(...)house [89] 16.739 ns 0.4468 ns 1.3033 ns 16.853 ns
完整的测试代码
using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace CorePerformanceTest
{
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<StringUpperTest>();
}
}
public class StringUpperTest
{
[Params("red", "red house", "red red red red red red red red red red red red red red red red red red red red red house")]
public string Data;
[Benchmark]
public string Marcell() => Data.Marcell();
[Benchmark]
public string L33t() => Data.L33t();
}
internal static class StringExtensions
{
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);
}
public static string L33t(this string s)
{
static void ThrowError() => throw new ArgumentException("There is no first letter");
if (string.IsNullOrEmpty(s))
ThrowError(); // IMPORTANT: Do not "throw" here!
return string.Create(s.Length, s, (chars, state) =>
{
state.AsSpan().CopyTo(chars);
chars[0] = char.ToUpper(chars[0]);
});
}
}
}
请让我知道你是否可以让它更快!
string.IsNullOrEmpty
之后使用 throw 关键字(重要提示:不要在此处“抛出”!)?
throw
关键字,但它的存在会阻止某些编译器优化,例如内联。您可以在有或没有它的情况下运行示例,您会发现它确实会影响性能。
最快的方法:
private string Capitalize(string s){
if (string.IsNullOrEmpty(s))
{
return string.Empty;
}
char[] a = s.ToCharArray();
a[0] = char.ToUpper(a[0]);
return new string(a);
}
测试显示下一个结果(以 1,0000,000 个符号作为输入的字符串):
s
参数。
由于这个问题是关于最大化性能,所以我采用 Darren's version 来使用 Span
,这样可以减少垃圾并将速度提高约 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 纳秒 0.3888 纳秒 0.3637 纳秒
完整的测试代码
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);
}
}
}
stackalloc
将破坏堆栈。
string.Create()
查看我的 improved answer。
尝试这个:
static public string UpperCaseFirstCharacter(this string text) {
return Regex.Replace(text, "^[a-z]", m => m.Value.ToUpper());
}
检查字符串是否不为空,将第一个字符转换为大写,将其余字符转换为小写:
public static string FirstCharToUpper(string str)
{
return str?.First().ToString().ToUpper() + str?.Substring(1).ToLower();
}
如果性能/内存使用是一个问题,那么这个只创建一 (1) 个 StringBuilder 和一 (1) 个与原始字符串大小相同的新字符串。
public static string ToUpperFirst(this string str) {
if(!string.IsNullOrEmpty(str)) {
StringBuilder sb = new StringBuilder(str);
sb[0] = char.ToUpper(sb[0]);
return sb.ToString();
} else return str;
}
char[]
来完成,而不是让 StringBuilder
的所有基础结构包装它。使用 str.ToCharArray()
代替 new StringBuilder(str)
,使用 new string(charArray)
代替 sb.ToString()
。 StringBuilder
模拟字符数组本机公开的索引类型,因此实际的 .ToUpper
行可以基本相同。 :-)
ToCharArray
执行此操作,正如 @JonathanGilbert 所建议的那样
由于我碰巧也在做这件事,并且正在四处寻找任何想法,这就是我找到的解决方案。它使用 LINQ,并且能够将字符串的第一个字母大写,即使第一次出现的不是字母。这是我最终制作的扩展方法。
public static string CaptalizeFirstLetter(this string data)
{
var chars = data.ToCharArray();
// Find the Index of the first letter
var charac = data.First(char.IsLetter);
var i = data.IndexOf(charac);
// capitalize that letter
chars[i] = char.ToUpper(chars[i]);
return new string(chars);
}
我确信有一种方法可以稍微优化或清理它。
如果您只关心第一个字母是否大写,而字符串的其余部分无关紧要,您可以选择第一个字符,将其设为大写,然后将其与字符串的其余部分连接,而无需原始第一个字符。
String word ="red house";
word = word[0].ToString().ToUpper() + word.Substring(1, word.length -1);
//result: word = "Red house"
我们需要将第一个字符转换为 ToString(),因为我们是把它作为一个 Char 数组来读取的,而 Char 类型没有 ToUpper() 方法。
这是一种将其作为扩展方法的方法:
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);
}
string.Format
太过分了;只需执行 text.Substring(0, 1).ToUpper() + text.Substring(1)
。
我在 C# Uppercase First Letter - Dot Net Perls 中发现了一些东西:
static string UppercaseFirst(string s)
{
// Check for empty string.
if (string.IsNullOrEmpty(s))
{
return string.Empty;
}
// Return char and concat substring.
return char.ToUpper(s[0]) + s.Substring(1);
}
这会做到这一点,尽管它也会确保没有错误的大写字母不在单词的开头。
public string(string s)
{
System.Globalization.CultureInfo c = new System.Globalization.CultureInfo("en-us", false)
System.Globalization.TextInfo t = c.TextInfo;
return t.ToTitleCase(s);
}
s
进行空检查。
string emp="TENDULKAR";
string output;
output=emp.First().ToString().ToUpper() + String.Join("", emp.Skip(1)).ToLower();
String
可以是任何它的 Upper
或 Lower
。所以它是所有字符串的通用解决方案。
Join
而不是 emp.First().ToString().ToUpper() + emp.Substring(1);
?可能也需要更具防御性:output = string.IsNullOrEmpty(emp) ? string.Empty : [...]
。另外,首先,同意@CarlosMuñoz - 您不需要 ToLower()
来回答 OP 的问题。
Substring
也是一种很好的代码编写风格,我同意您修剪代码的解决方案,但在这种情况下编写 ToLower()
是一种很好的编程习惯。string
可以是任何东西 在 Upper
情况下或 Lower
情况下取决于用户输入,我给出了一个通用的解决方案。
我们可以这样做(C# 8.0、.NET 5):
input?.Length > 0 ? char.ToUpperInvariant(input[0]) + input[1..] : input
我相信这足够短,可以内联。
如果 input
是一个空字符串,我们会得到一个空字符串。如果 input
是 null
,我们得到 null
。
否则,代码将获取第一个字符 input[0]
并使用 char.ToUpperInvariant
将其转换为大写。并连接其余的 input[1..]
。
编译器会将范围访问转换为对 Substring
的调用,此外它还可以利用我们已经获得长度这一事实。
相对于公认的答案,这具有不使用 LINQ 的优势。其他一些答案将字符串转换为数组只是为了获取第一个字符。这段代码也不这样做。
如果您更喜欢扩展方法,可以这样做:
public static string FirstCharToUpper(this string input) =>
input?.Length > 0 ? char.ToUpperInvariant(input[0]) + input[1..] : input;
如果你喜欢扔怎么办?好的,让它抛出:
public static string FirstCharToUpper(this string input) =>
input switch
{
null => throw new ArgumentNullException(nameof(input)),
_ => input.Length > 0 ? char.ToUpperInvariant(input[0]) + input[1..] : input
};
这里大致等价的代码(因为我们正在做一个扩展方法,我们可以更冗长一些):
public static string FirstCharToUpperEquivalent(this string input)
{
if (input == null)
{
throw new ArgumentNullException(nameof(input));
}
var length = input.Length;
if (length == 0)
{
return input;
}
string firstCharacter = char.ToUpperInvariant(input[0]).ToString();
return string.Concat(firstCharacter, input.Substring(1, length - 1));
}
我做了一个 1000 轮 155 个单词的基准测试(所以它们被称为 155000 次),结果如下:
Benchmarking type Tests
TestAccepted 00:00:00.0465979
TestProposalNoThrow 00:00:00.0092839
TestProposalDoThrow 00:00:00.0092938
TestProposalEquival 00:00:00.0091463
我使用 Jon Skeet 的 Simple microbenchmarking in C# 中的代码在 Windows 10、Intel Core i3 上运行它。
当您只需要以下内容时,这里似乎有很多复杂性:
/// <summary>
/// Returns the input string with the first character converted to uppercase if a letter
/// </summary>
/// <remarks>Null input returns null</remarks>
public static string FirstLetterToUpperCase(this string s)
{
if (string.IsNullOrWhiteSpace(s))
return s;
return char.ToUpper(s[0]) + s.Substring(1);
}
值得注意的点:
这是一种扩展方法。如果输入为空、空或空格,则输入按原样返回。 String.IsNullOrWhiteSpace 是在 .NET Framework 4 中引入的。这不适用于旧框架。
IsNullOrWhiteSpace
而不是 IsNullOrEmpty
的唯一好处,是如果您要查找并更改第一个非空白。但你没有 - 你总是在 s[0]
上操作。因此,使用 IsNullOrWhiteSpace
毫无意义[在语义和性能上]。
IsNullOrWhiteSpace
的这种用法让我感到困扰,是粗心的读者可能会认为“他检查了空格,所以下面的代码确实找到并更改了一个字母,即使它前面有空格”。由于您的代码无法更改以空格开头的“首字母”,因此使用 IsNullOrWhiteSpace
只会误导读者。
我认为下面的方法是最好的解决方案。
class Program
{
static string UppercaseWords(string value)
{
char[] array = value.ToCharArray();
// Handle the first letter in the string.
if (array.Length >= 1)
{
if (char.IsLower(array[0]))
{
array[0] = char.ToUpper(array[0]);
}
}
// Scan through the letters, checking for spaces.
// ... Uppercase the lowercase letters following spaces.
for (int i = 1; i < array.Length; i++)
{
if (array[i - 1] == ' ')
{
if (char.IsLower(array[i]))
{
array[i] = char.ToUpper(array[i]);
}
}
}
return new string(array);
}
static void Main()
{
// Uppercase words in these strings.
const string value1 = "something in the way";
const string value2 = "dot net PERLS";
const string value3 = "String_two;three";
const string value4 = " sam";
// ... Compute the uppercase strings.
Console.WriteLine(UppercaseWords(value1));
Console.WriteLine(UppercaseWords(value2));
Console.WriteLine(UppercaseWords(value3));
Console.WriteLine(UppercaseWords(value4));
}
}
Output
Something In The Way
Dot Net PERLS
String_two;three
Sam
解决您的问题的可能解决方案:
public static string FirstToUpper(this string lowerWord)
{
if (string.IsNullOrWhiteSpace(lowerWord) || string.IsNullOrEmpty(lowerWord))
return lowerWord;
return new StringBuilder(lowerWord.Substring(0, 1).ToUpper())
.Append(lowerWord.Substring(1))
.ToString();
}
我想提供一个“最大性能”的答案。在我看来,“最大性能”的答案涵盖了所有场景,并提供了解决这些场景的问题的答案。所以,这是我的答案。有这些原因:
IsNullOrWhiteSpace 说明只是空格或空/空的字符串。 .Trim() 删除字符串前后的空白。 .First() 采用 IEnumerable
扩展上述 Carlos 的问题,如果您想将多个句子大写,可以使用以下代码:
/// <summary>
/// Capitalize first letter of every sentence.
/// </summary>
/// <param name="inputSting"></param>
/// <returns></returns>
public string CapitalizeSentences (string inputSting)
{
string result = string.Empty;
if (!string.IsNullOrEmpty(inputSting))
{
string[] sentences = inputSting.Split('.');
foreach (string sentence in sentences)
{
result += string.Format ("{0}{1}.", sentence.First().ToString().ToUpper(), sentence.Substring(1));
}
}
return result;
}
这是对我有用的代码:
private string StringLetterUppercase(string input)
{
if (input == null)
{
throw new ArgumentNullException(nameof(input));
}
else if (input == "")
{
throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input));
}
else
{
return input.First().ToString().ToUpper() + input.Substring(1);
}
}
似乎这里给出的解决方案都不会处理字符串之前的空格。
只是将其添加为一个想法:
public static string SetFirstCharUpper2(string aValue, bool aIgonreLeadingSpaces = true)
{
if (string.IsNullOrWhiteSpace(aValue))
return aValue;
string trimmed = aIgonreLeadingSpaces
? aValue.TrimStart()
: aValue;
return char.ToUpper(trimmed[0]) + trimmed.Substring(1);
}
它应该处理 this won't work on other answers
(该句子开头有一个空格),如果您不喜欢空格修剪,只需传递一个 false
作为第二个参数(或将默认值更改为 false
,然后通过true
如果你想处理空间))。
这是最快的方法:
public static unsafe void ToUpperFirst(this string str)
{
if (str == null)
return;
fixed (char* ptr = str)
*ptr = char.ToUpper(*ptr);
}
在不更改原始字符串的情况下:
public static unsafe string ToUpperFirst(this string str)
{
if (str == null)
return null;
string ret = string.Copy(str);
fixed (char* ptr = ret)
*ptr = char.ToUpper(*ptr);
return ret;
}
System.String
对象的 任何 情况都会看到字符串从其下方发生变化。考虑是否将给定的 System.String
对象用作 Dictionary<string, TValue>
中的键 - 字符串的散列可能突然不正确,将值放入错误的存储桶并破坏数据结构。第二个版本是唯一可以使用的“安全”版本,甚至在技术上它也违反了运行时的假设和 CLR 规范。
string
类的不变性是不可接受的 - 违反了健全的编码原则。如果程序员想要一个可变字符串,他们应该围绕 char[]
构建一个自定义类。方法 #2:无需进行 unsafe
编程即可完成此操作。请参阅使用 ToCharArray
的 Darren's answer。
以下功能适用于所有方式:
static string UppercaseWords(string value)
{
char[] array = value.ToCharArray();
// Handle the first letter in the string.
if (array.Length >= 1)
{
if (char.IsLower(array[0]))
{
array[0] = char.ToUpper(array[0]);
}
}
// Scan through the letters, checking for spaces.
// ... Uppercase the lowercase letters following spaces.
for (int i = 1; i < array.Length; i++)
{
if (array[i - 1] == ' ')
{
if (char.IsLower(array[i]))
{
array[i] = char.ToUpper(array[i]);
}
}
}
return new string(array);
}
我发现了here。
char.IsWhiteSpace( array[ i -1 ] )
而不是 .. == ' '
来处理所有空白。 2)删除做 if (char.isLower(..))
的两个地方 - 它们没有任何作用。 ToUpper
如果字符不是小写,则什么也不做。
String.Join
的第一个参数是用于连接第二个参数给出的字符串的分隔符。var arr = input.ToCharArray(); arr[0] = Char.ToUpperInvariant(arr[0]); return new String(arr);
可能会提高一些速度,因为您创建的不可变对象较少(尤其是您正在跳过String.Join
)。这当然取决于字符串的长度。"Argh!"
以符合 大写首字母 规则。 ;)