我注意到在我们的代码中,我们有很多对
string.Split(string[],StringSplitOptions)
的调用,如下所示:
input.Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries)
或者像这样:
input.Split(new string[] { "\r", "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries)
我的直觉告诉我,我可以将它们全部替换为类似的东西,以提高可读性(并可能提高性能,尽管我不太关心这一点),并且不会有副作用:
static readonly string CrLfStrings = new char[] { '\r', '\n' };
input.Split(CrLfStrings, StringSplitOptions.RemoveEmptyEntries)
事实上,我的直觉告诉我,对于任何字符集 SC,如果使用
string.Split(string[],StringSplitOptions)
和一组包含 SC的所有单字符字符串的字符串来调用
RemoveEmptyEntries
,并且其中所有剩余的字符串仅由 SC 中的字符组成,我可以用 string.Split(char[],StringSplitOptions)
和 SC调用
RemoveEmptyEntries
来替换它,并且不会有任何副作用。
我的预感正确吗?可以证明吗?如果是这样,即使我不理解周围的代码,我也可以很高兴地在任何地方进行替换。
换句话说,下面的
Compare
方法对于任何非空字符串都会返回 true 吗?我对边缘情况不太感兴趣,其中一个会耗尽内存,而另一个则不会。
using System;
using System.Linq;
private static bool Compare(string input)
{
string[] prev = null;
var funcs = new Func<string, string[]>[] { Split0, Split1, Split2 };
for (int i = 0; i < funcs.Length; i++)
{
var curr = funcs[i](input);
if (i != 0 && !(curr.SequenceEqual(prev)))
{
return false;
}
prev = curr;
}
return true;
}
private static string[] Split0(string input) =>
input.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
private static string[] Split1(string input) =>
input.Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);
private static string[] Split2(string input) =>
input.Split(new string[] { "\r", "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
您只需提交
string
,.Net 将使用与 char\[\]
匹配的 重载,如下所示:
input.Split("\r\n", StringSplitOptions.RemoveEmptyEntries);
但是为了我的钱,我会使用
StringReader
:
public static IEnumerable<string> AsLines(this string input)
{
string line = null;
using var rdr = new System.Text.StringReader(input);
while (null != (line = rdr.ReadLine())
{
yield return line;
}
}
然后:
foreach(var line in input.AsLines().Where(line => !string.IsNullOrEmpty(line)))
{
// do something with each line
}