那麼,你不需要第一個電話ToCharArray()
開始 - 字符串實現IEnumerable<char>
。不過,我同意在這種情況下,StringBuilder和循環可能更合適。
我不知道什麼string.Concat(char [])做副手,順便說一句 - 爲什麼你不只是使用字符串構造函數,它需要一個字符數組?換句話說,經過這些修改:
static string SanitizeXml(string xml)
{
return new string (xml.Where(c => IsLegalXmlChar(c)).ToArray());
}
我還是更喜歡StringBuilder的解決方案,但可能對於通常的情況得到改善(其中有幾個非法字符)給予開始用適當的容量:
string SanitizeXml(string xml)
{
var buffer = new StringBuilder(xml.Length);
foreach(char c in xml)
{
if (IsLegalXmlChar(c))
{
buffer.Append(c);
}
}
return buffer.ToString();
}
一種替代我之前沒有想到的可能是對的StringBuilder擴展方法:
// Can't just call it Append as otherwise StringBuilder.Append(object) would
// be used :(
public static StringBuilder AppendSequence(this StringBuilder builder,
IEnumerable<char> sequence)
{
foreach (char c in sequence)
{
builder.Append(c);
}
return builder;
}
然後,你可以使用它像這樣:
xml = new StringBuilder(xml.Length)
.AppendSequence(xml.Where(IsLegalXmlChar)
.ToString();
(你可以有其他重載AppendSequence採取的IEnumerable等,如果你想。)
編輯:另一種方法是避免調用追加經常使用,而不是the overload which appends a substring。然後,您可以再建立StringBuilder的,像一個擴展方法(沒有經過充分測試,我害怕 - 我還沒有嘗試過,甚至其編譯):
public static StringBuilder AppendWhere(this StringBuilder builder,
string text,
Func<char, bool> predicate)
{
int start = 0;
bool lastResult = false;
for (int i=0; i < text.Length; i++)
{
if (predicate(text[i]))
{
if (!lastResult)
{
start = i;
lastResult = true;
}
}
else
{
if (lastResult)
{
builder.Append(text, start, i-start);
lastResult = false;
}
}
}
if (lastResult)
{
builder.Append(text, start, text.Length-start);
}
return builder;
}
使用的例子:
xml = new StringBuilder(xml.Length).AppendWhere(xml, IsLegalXmlChar)
.ToString();
另一種方法是將其更改爲String上的擴展方法,懶惰地創建StringBuilder,並且如果以start = 0結束,只返回原始字符串。
爲什麼要刪除非法字符,而不是讓框架爲你逃脫? – 2009-01-18 19:30:13
非法字符通常會通過文檔和數據轉換進入。例如,沒有理由在XML文檔中使用'\ b',事實上,您的主板會產生鈴聲,任何嘗試使用這些數據的.NET XML API都會拋出異常。 – core 2009-01-24 21:41:55