我有一个简单的过程来删除XML中非法的所有字符串:
string SanitizeXml(string xml)
{
return string.Concat
(xml.ToCharArray().Where(c => IsLegalXmlChar(c)).ToArray());
}
Run Code Online (Sandbox Code Playgroud)
这很好,很简洁.但我很担心它的表现.使用简单的for循环可以轻松完成同样的事情:
string SanitizeXml(string xml)
{
var buffer = new StringBuilder();
foreach(char c in xml)
{
if (IsLegalXmlChar(c))
{
buffer.Append(c);
}
}
return buffer.ToString();
}
Run Code Online (Sandbox Code Playgroud)
在我看来,在第二个例子中,xml被转换为char [],而Where()的IEnumerable <char>被转换为char [].我似乎用LINQ做了很多 - 在数组和枚举之间进行了更改.
我应该关注这件事吗?一般来说,当一个明确的替代方案可能更加冗长时,依赖于LINQ扩展方法,我将获得什么样的性能影响.
也许这是一个过于宽泛的问题.
好吧,你不需要第一次调用ToCharArray()
- 字符串实现IEnumerable<char>
.但是,我同意在这种情况下StringBuilder和循环可能更合适.
我不确定是什么string.Concat(char [])随便做什么,顺便说一句 - 你为什么不只是使用带有char数组的字符串构造函数?换句话说,经过这些修改:
static string SanitizeXml(string xml)
{
return new string (xml.Where(c => IsLegalXmlChar(c)).ToArray());
}
Run Code Online (Sandbox Code Playgroud)
我仍然更喜欢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();
}
Run Code Online (Sandbox Code Playgroud)
我之前没有想到的一个替代方案可能是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;
}
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样使用它:
xml = new StringBuilder(xml.Length)
.AppendSequence(xml.Where(IsLegalXmlChar)
.ToString();
Run Code Online (Sandbox Code Playgroud)
(如果你愿意的话,你可以让AppendSequence有其他重载来获取IEnumerable等.)
编辑:另一种选择可能是避免经常调用Append,而是使用附加子字符串的重载.然后你可以再次为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;
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
xml = new StringBuilder(xml.Length).AppendWhere(xml, IsLegalXmlChar)
.ToString();
Run Code Online (Sandbox Code Playgroud)
另一种方法是将它更改为String上的扩展方法,懒惰地创建StringBuilder,如果你以start = 0结束,只需返回原始字符串.
归档时间: |
|
查看次数: |
995 次 |
最近记录: |