“string”=“string”会花费更多内存

时间:2018-01-23 17:11:03

标签: c# .net string memory

作为我对此代码所做的重构的一部分,我遇到了这段代码,我正在讨论什么更正确/更有效?

之前

string CutHeadAndTail(string pattern)
{
    if (pattern[0] == '*')
    {
        pattern = pattern.Substring(1);
    }
    if (pattern[pattern.Length - 1] == '*')
    {
        pattern = pattern.Substring(0, pattern.Length - 1);
    }
    return pattern;
}

private string RemoveAllowedAstrisks(string pattern)
{
    pattern = pattern[0] == '*'?pattern.Substring(1): pattern;
    pattern = pattern[pattern.Length - 1] == '*' ? pattern.Substring(0, pattern.Length - 1) : pattern;

    return pattern;
}

什么更好?
我在想pattern = pattern[0] == '*'?pattern.Substring(1): pattern;这一行 意思是,从可读性的角度来看,我更喜欢第二种。但另一方面,这个表达式的含义是以下两个选项:

  1. pattern[0]=='*' - >在这种情况下,模式将更改为pattern.Substring(1)
  2. else - > pattern = pattern
  3. 如果我选择第一种方式(忽略命名等),我只有第一种选择:

    1. if (pattern[0] == '*')
      {
         pattern = pattern.Substring(1);
      }
      
    2. return pattern;
      
    3. 底线:行pattern = pattern会花费更多内存吗?

5 个答案:

答案 0 :(得分:1)

如果您允许从字符串的开头和结尾剪切所有*个字符(如"**some string**"),那么您可以这样做:

private string RemoveAllowedAstrisks(string pattern)
{
    return pattern?.Trim('*');
}

答案 1 :(得分:0)

执行此操作的最佳方法可能是via a regex

using System.Text.RegularExpressions;

...
private static Regex leadingTrailingAsterisks = new Regex("(^\\*)|(\\*$)");
private static string RemoveAllowedAsterisks(string pattern)
{
    return leadingTrailingAsterisks.Replace(pattern, "");
}

答案 2 :(得分:0)

我更喜欢第一种方式,因为它更简单,并且使编译器更容易进行任何优化。

说实话,我不知道编译器是否会在第二种方法中优化pattern = pattern。它可能。只有速度测试才能帮助您确定。

就个人而言,我发现第二种方法更简洁但不易读。如果我不需要这样做,我也不会编写为自己分配变量的代码。

更可读的方式是使用string.Trim(),但我认为效率较低。

答案 3 :(得分:0)

我已检查生成的IL代码以查看创建的内容。

IL_000e: ldloc.0      // hello
IL_000f: ldc.i4.0     
IL_0010: callvirt     instance char [mscorlib]System.String::get_Chars(int32)
IL_0015: ldc.i4.s     42 // 0x2a
IL_0017: beq.s        IL_001c
IL_0019: ldloc.0      // hello
IL_001a: br.s         IL_0023
IL_001c: ldloc.0      // hello
IL_001d: ldc.i4.1     
IL_001e: callvirt     instance string [mscorlib]System.String::Substring(int32)
IL_0023: stloc.0      // hello

如您所见,如果运行逻辑语句的ldloc.0分支(:),则IL_0019被激活。在此之后,代码跳转到执行IL_0023的{​​{1}}。

这可能是值类型的问题,但stloc.0是引用类型,并且此类赋值根本不会影响内存。为了证明这一点,我创建了一个大字符串并运行了一些string分配。堆大小永远不会改变。

value = value

Heap sizes

答案 4 :(得分:0)

如何进行以下操作:计算是从前面还是后面或两者中修剪一个字符,如果是,则返回一个子字符串,否则返回字符串本身。

string CutHeadAndTail(string pattern)
{
    var s = pattern[0] == '*' ? 1 : 0;
    var e = pattern[pattern.Length - 1] == '*' ? 1 : 0;
    return (s > 0 || e > 0) ?
        pattern.Substring(s, pattern.Length - s - e) :
        pattern;
}