Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “string”=“string”是否占用更多内存_C#_.net_String_Memory - Fatal编程技术网

C# “string”=“string”是否占用更多内存

C# “string”=“string”是否占用更多内存,c#,.net,string,memory,C#,.net,String,Memory,作为我对这段代码进行重构的一部分,我遇到了这段代码,我正在讨论什么更正确/更有效 之前: 之后: 什么更好? 我考虑的是线型图案=图案[0]='*'?图案。子字符串1:pattern; 也就是说,从可读性的角度来看,我更喜欢第二种。但另一方面,此表达式的含义是以下两个选项: 模式[0]='*'->在这种情况下,模式将更改为pattern.Substring1 else->pattern=模式 如果我选择第一种方式,忽略命名等,我只有第一种选择: 底线:线条模式=模式需要更多内存吗?最好的方法可能

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

之前:

之后:

什么更好? 我考虑的是线型图案=图案[0]='*'?图案。子字符串1:pattern; 也就是说,从可读性的角度来看,我更喜欢第二种。但另一方面,此表达式的含义是以下两个选项:

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


底线:线条模式=模式需要更多内存吗?

最好的方法可能是


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

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

就我个人而言,我觉得第二种方法更简洁,但可读性不强。如果我不需要这样做,我就不会编写为自身分配变量的代码


一个更可读的方法是使用String .Trimm,但是我认为效率不高。

< P>如果你允许从字符串的开头和结尾修剪所有**字符,比如**一些字符串**,那么你可以这样做:

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

我已经检查了生成的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
如您所见,如果逻辑语句的:分支运行IL0019,则会执行ldloc.0。紧接着,代码跳转到执行stloc.0的IL_0023

这可能是值类型的问题,但字符串是引用类型,这样的赋值根本不会影响内存。为了证明这一点,我创建了一个大字符串并运行了一些value=value赋值。堆大小从未改变

string hello = new string('a', 3202340);
hello = hello;
hello = hello;

下面如何:计算是从前面还是后面修剪一个字符,或者同时从前面或后面修剪两个字符,如果是,则返回一个子字符串,否则返回字符串本身

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;
}

它是1。正如汉斯指出的那样,这并不重要。2.string是一种引用类型,所以pattern=pattern完全不起作用。我不确定如何翻译成IL和机器码,如果这没有得到很好的优化,引用可能会从内存复制到cpu寄存器并再次复制到同一内存位置。请不要担心性能,但我想知道是否存在实际差异?@Roni检查差异的最简单方法是查看IL。使用LinqPad或类似工具最大的区别在于原始代码清晰易读。OP似乎担心内存使用,而不是速度。我猜Regex实例需要比当前解决方案更多的内存。使用Regex代替两个基本的字符串操作调用几乎总是大材小用。他询问内存和性能,询问更小的短语和编译,这太过分了。如果因为内存开销而考虑两次分配字符串,则正则表达式会执行一次一站式替换,即使它只创建了一次,也比当前解决方案中多了一次。不过,这稍微改变了原始方法的约定。RemoveAllowedStrisks**foo**将导致原始版本中的*foo*和此版本中的foo。这实际上应该是一个错误,绝对同意,但修剪选项不能作为解决方案,因为它破坏了以前的行为。@Roni:是的,它的逻辑不完全相同。例如,如果字符串以多个星号*开头,它将删除所有星号,而代码仅删除第一个星号。
using System.Text.RegularExpressions;

...
private static Regex leadingTrailingAsterisks = new Regex("(^\\*)|(\\*$)");
private static string RemoveAllowedAsterisks(string pattern)
{
    return leadingTrailingAsterisks.Replace(pattern, "");
}
private string RemoveAllowedAstrisks(string pattern)
{
    return pattern?.Trim('*');
}
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
string hello = new string('a', 3202340);
hello = hello;
hello = hello;
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;
}