我该先使用 string.Contains() 还是 string.Replace()?

14

在执行字符串替换之前是否需要这个if语句是多余的吗?

 if (myString.Contains(oldValue))
 {
      myString = myString.Replace(oldValue, newValue);
 }

5
不试试就不知道。 - adv12
3
Visual Studio最新版提供了交互式的C#提示符,非常适合用于实验:查看(View) -> 其他窗口(Other Windows) -> C# 交互式(C# Interactive) - pixelmike
5
你不能通过“试一试”来推断已记录的合同内容。 - IInspectable
3
考虑一个假设规范,规定如果 oldValue 不存在,则结果未指定。你如何通过尝试来推断这一点?返回值又是怎样的呢?它总是返回一个新实例吗?有时会返回相同的实例吗?尝试可能只会产生关于特定 实现 的细节,并不能保证合同。建议去尝试并不是好主意,虽然在 .NET 上尝试不像其他平台那样容易/常见,但依旧是糟糕的建议。 - IInspectable
@IInspectable - 这听起来确实很有道理,但 OP 正在尝试理解这个特定的实现。即使实现是模糊规格的结果,它现在也是现状 - Microsoft 永远不会改变它 - 所以你可以假设实现现在就是规格。 - Enigmativity
显示剩余10条评论
4个回答

19

有关 String.Replace 的所有详细信息均在文档中:

返回值:
返回一个字符串,该字符串与当前字符串等效,除了所有实例的 oldValue 都被替换为 newValue如果当前实例中未找到 oldValue,则该方法返回不经修改的当前实例。

if 语句不是必需的。

if 语句甚至不是性能优化,因为如果在当前实例中未找到 oldValue,则 String.Replace 返回相同的对象实例。我使用以下代码进行了验证:

namespace StringReplaceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "Test";
            string s2 = s.Replace("Foo", "Bar");
            string s3 = s.Replace("es", "tt");
        }
    }
}

使用方便的创建对象 ID功能(右键单击LocalsAutoWatch窗口中的符号;有关详细信息,请参见常用表达式求值器功能)生成了以下输出:

s  | "Test" {$1}
s2 | "Test" {$1}
s3 | "Tttt" {$2}

1
引用的ReferenceSource注释仅适用于找到oldValue的情况。 StringBuilder通过Replace调用进行了变异。使用安全代码无法改变string,因此必须分配一个新实例。您答案的第一部分是正确的(使用.NET 4.5.1进行测试)。如果未找到oldValue,则对于已经过国际化和未经国际化的字符串,都将返回相同的原始实例。 - Kirill Shlenskiy
1
@KirillShlenskiy: 看似不一致的信息引起了我的好奇心。我检查了行为,并得出了你在评论中发表的相同结论。 - IInspectable
这是一个很好的答案。我请求OP接受这个答案,而不是我的。我的只有两三行,而这个答案更加详细。 - Fᴀʀʜᴀɴ Aɴᴀᴍ
问题在于性能,而不是可能性。做一个包含然后替换的操作比仅仅替换更高效吗?我的猜测是你最好还是直接进行替换,因为如果旧值没有被找到,那么包含和替换都必须搜索整个字符串。 - Eric Clark

4

由于String.Replace()函数在字符串不包含指定值时不会抛出异常,因此验证是不必要的。这将导致多余的条件判断。


1
我知道这是一个旧的帖子,但我想提供我的意见!
如果我的说法有误,请让我知道,但我刚在我的环境中尝试了一下,似乎是可行的!:)
大多数情况下,是的,replace函数将为您执行包含操作,因此没有必要单独使用它。但是,如果您的“新值”是从方法派生的,则这样做是有优势的-具体取决于在方法内获取该值所需的工作量!
例如,在以下情况下不优越:
我正在为应用程序发送的电子邮件正文制作“字符串替换器”。例如,如果用户在电子邮件正文中有“[[用户名]]”,我想用收件人的名字替换它。幸运的是,我们的框架将该信息存储在内存中,因此我不介意为此进行单个替换。

例子说明何时使用它更有优势:

在与上述相同的前提下,另一个替换器是“[[Payments]]”。这将进入数据库,并带出用户进行的前1000笔交易的日志,然后对检索到的数据进行处理并显示电子邮件正文中的详细信息。想象一下,每次用户从应用程序发送电子邮件时都必须执行所有这些操作,即使它不包含“[[Payments]]”关键字!在调用生成“[[Payments]]”字符串值的方法之前进行包含判断,在这里真的很值得!

长话短说,这取决于您的实现,但在大多数情况下-是不必要的。


1
这是对另一个问题的回答:“我应该避免不必要的昂贵计算吗?” - IInspectable
1
问题在于Replace方法会评估newValue,即使它最终不使用它,因此如果newValue是一个昂贵的操作,则最好在进行替换之前检查它是否包含匹配项。 - Aki

-3
根据我的经验,如果你需要进行多次替换(而且只需要一次替换),最好使用Contains()方法进行检查。在我的情况下,这有助于提高代码的运行速度(几乎翻倍)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接