在C#中执行替换之前执行检查是否更有效?

在C#中执行替换之前执行检查是否更有效?,c#,text,replace,C#,Text,Replace,这几乎是一个学术问题,但我对它的答案很好奇 假设您有一个对数据集中的每一行执行例程替换的循环。假设有10000行这样的行 这样做是否更有效: Row = Row.Replace('X', 'Y'); if (Row.Contains('X')) Row = Row.Replace('X', 'Y'); 或者检查行是否包含首先要替换的字符,如下所示: Row = Row.Replace('X', 'Y'); if (Row.Contains('X')) Row = Row.Repla

这几乎是一个学术问题,但我对它的答案很好奇

假设您有一个对数据集中的每一行执行例程替换的循环。假设有10000行这样的行

这样做是否更有效:

 Row = Row.Replace('X', 'Y');
 if (Row.Contains('X')) Row = Row.Replace('X', 'Y');
或者检查行是否包含首先要替换的字符,如下所示:

 Row = Row.Replace('X', 'Y');
 if (Row.Contains('X')) Row = Row.Replace('X', 'Y');

在效率方面有什么不同吗?我意识到差异可能很小,我想知道一种方法是否比另一种更好,不管它可能有多好。此外,如果找到要替换的角色的概率为10%,而不是90%,您的答案会有所不同吗?

您需要首先在真实的数据集上进行测量,然后确定哪个性能更高。如果您的典型数据集通常没有任何内容,那么调用
Contains()
可能会更快(因为虽然
Replace
也会迭代字符串中的所有字符,但由于字符串的不可变性,会创建一个额外的字符串对象并进行垃圾收集),但是如果经常出现“X”,则,支票变成了一种浪费,实际上减慢了速度

此外,这通常不是第一个寻找和担心性能问题的地方。像聊天界面、网络I/O、web服务、数据库、文件I/O和GUI更新这样的事情对您的伤害要比这类事情大得多

如果您要执行类似的操作,并且如果
Row
从数据库返回(顾名思义),那么让数据库执行查询可能是另一种节省性能的方法。例如

select MyTextColumn from MyTable where MyTextColumn like '%X%'
然后对所有结果执行替换,因为您知道您只返回需要替换的结果

不过,这确实带来了其他问题-例如,在SQL Server中,如果上面的示例在
MyTextColumn
上包含索引,SQL Server将无法使用该索引,因为
like
参数以通配符开头(它不被视为“可搜索”)


总之,首先写正确性、可读性和维护,然后测量性能,并在需要的地方进行有针对性的改进。

第一个选项更快。为了检查子字符串是否存在,首先必须找到它。既然没有任何缓存机制,为什么不直接替换它呢?否则你会搜索两次。如果“X”出现多次,基本上会加倍努力。

请检查,
Row.Contains('X')
是一个O(n)函数,这意味着它每次迭代整个字符串一个字符,以查看该字符是否存在

Row.Replace('X','Y')
的工作方式完全相同,它每次检查一个字符


因此,如果您有了该检查,那么您可能会在字符串上迭代两次。如果您只是替换,您将在字符串上迭代一次。

不要忘记C#中的字符串是不可变的。这意味着他们无法改变

为了替换任何内容,它必须在内存中创建一个新字符串,并在其中复制数据,然后在以后对旧字符串进行垃圾收集


首先使用Contains()可以防止不必要的字符串数据创建、复制和垃圾收集,因此执行速度更快。

行的类型是什么?一串我看不出第二个应该更快的原因,除非
行的setter非常昂贵。在这种情况下,您可以首先将结果存储在一个局部变量中,检查它是否与之前不同,然后才将其分配到
谢谢。如果我不是在数据集上而是在原始字符串变量上进行替换,那么一种方法是否会始终优于另一种方法呢?“总之,首先编写可读性和维护,然后测量性能,并在需要的地方进行有针对性的改进。”我同意这一点。我想,我问题背后的问题是一个更加数学化的问题——然而,似乎因为每次调用Replace都已经包含了一个类似于我在第二个案例中给出的检查,那么该检查就不需要了。谢谢在所有情况下,没有一种方法会始终优于另一种方法。您需要编写功能正确且可读的代码,只有这样,您才能运行代码、进行测量并在必要时进行适当的性能改进。“在所有情况下,没有一种方法会始终优于另一种方法。”也许是这样,但这并不意味着一种方式不可能总是比所有其他方式更糟。在这种情况下,第二种方式似乎就是这样。如果你这么认为的话,我认为我的观点还不够清楚。关键是-证明它…谢谢你!我以为检查已经内置在Replace函数中,而您刚刚确认了它。这显然意味着做冗余和回答我的问题。此外,还有其他事情要考虑——创建多少个字符串对象,因此影响垃圾收集等等。最好的办法是不要尝试优化自己的头脑-运行代码,测量它,在特定的情况下,没有什么可考虑的,并且没有额外的对象创建-替换调用总是执行对包含的检查,因此在调用之前不必要这样做。这回答了我的问题。
Replace
如果不替换任何内容,为什么要创建一个新字符串?这是不正确的信息;在.Net
中,字符串
在更改时不会被复制,而是与指针一起构建。因此,如果没有改变,它肯定无法应对数据。源代码“Visual Basic.NET文本操作手册:字符串处理和正则表达式”