C#文件迭代性能-值得绕过字符串.性能为IsNullOrEmpty
本文关键字:性能 字符串 IsNullOrEmpty 值得 文件 迭代 | 更新日期: 2024-10-23 02:51:09
当前正在编写一个文件解析器,该解析器逐行运行数据文件并清理数据。性能是此应用程序的一个重要考虑因素。用户为数据列分配标签,让流程知道哪一列代表什么类型的数据,即哪一列是姓氏字段,哪一个是地址字段,哪是电话号码等等
我刚写完一堆清除电话号码的代码,并像这样应用:
public void CleanPhoneFields(FileRow row, List<Mapping> mappings)
{
// this will return empty if there's no field mapped with the "Telephone Number" tag
string phoneNumber = GetValueByAssignedLabel(row, mappings, "Telephone Number");
if(!string.IsNullOrEmpty(phoneNumber))
{
CleanTelephoneNumber(phoneNumber);
}
}
public void ProcessFile(FileContents fileContents)
{
foreach (FileRow row in fileContents.FileRows)
{
// does other cleaning functions too
CleanPhoneFields(row, fileContents.Mappings, fc);
}
}
然后我意识到,逐行检查电话字段是没有必要的——文件中的第一行是这样,所有行都是这样。所以我最好这样做:
public void CleanPhoneFields(FileRow row, List<Mapping> mappings)
{
// this will return empty if there's no field mapped with the "Telephone Number" tag
string phoneNumber = GetValueByAssignedLabel(row, mappings, "Telephone Number");
CleanTelephoneNumber(phoneNumber);
}
public void ProcessFile(FileContents fileContents)
{
bool firstLine = true;
bool cleanPhoneNeeded = false;
foreach (FileRow row in fileContents.FileRows)
{
if(firstLine)
{
cleanPhoneNeeded = !string.IsNullOrEmpty(GetValueByAssignedLabel(row, fileContents.Mappings, "Telephone Number"));
firstLine = false;
}
if(cleanPhoneNeeded)
{
CleanPhoneFields(row, fileContents.Mappings, fc);
}
}
}
我仍然需要去获取每一行的字段值,所以在这种情况下,我所"保存"的只是取消对字符串的调用。每行为IsNullOrEmpty。另一方面,第二个代码(在我看来)可读性稍差,并且丢失了一些防御性代码。
正在摆脱字符串。IsNullOrEmpty会在处理周期方面为我节省很多吗?第二种方法的小缺点值得吗。或者有更好的方法来解决这个问题吗?
使用System.Diagnostics命名空间中的Stopwatch类,您可以测量程序执行所需的时间(以毫秒为单位)。
尝试使用和不使用空和空检查器(尽管毫无疑问,有很多可测量的差异)
更多信息请点击此处:https://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch(v=vs.110).aspx
IMO string.IsNullOrEmpty
调用的影响可以忽略不计。
不过,第二个解决方案的好处是,它消除了整个CleanPhoneFields
调用,更重要的是,消除了似乎是最慢部分的GetValueByAssignedLabel
调用(除了实际的Clean
部分,当需要时无法避免)。
然而,我会对原始过程进行稍微不同的重构,在可读性和性能之间保持平衡。
首先,我将使用CleanPhoneFields
方法返回bool
:
public bool CleanPhoneFields(FileRow row, List<Mapping> mappings)
{
// this will return empty if there's no field mapped with the "Telephone Number" tag
string phoneNumber = GetValueByAssignedLabel(row, mappings, "Telephone Number");
if(string.IsNullOrEmpty(phoneNumber)) return false;
CleanTelephoneNumber(phoneNumber);
return true;
}
那么主要的方法可能是这样的:
public void ProcessFile(FileContents fileContents)
{
bool cleanPhoneFields = true;
foreach (FileRow row in fileContents.FileRows)
{
if (cleanPhoneFields)
cleanPhoneFields = CleanPhoneFields(row, fileContents.Mappings, fc);
// Other stuff
}
}
string.IsNullOrEmpty
实际上没有成本(无论如何都不用担心)
另一方面,您可能想做的是将"电话号码"声明为private const
字段,以防止每次调用CleanPhoneFields
方法时都创建它。
您也可以使用string.Intern
来防止。。。