string.Empty vs.“” - 这改变了吗?

时间:2015-06-02 17:49:01

标签: c#

根据this answerCSV::Converters[:mytime] = lambda do |s| DateTime.parse(s.tr(?E, ?T)) rescue s end CSV.parse("20150515000019", converters: :mytime) # [[#<DateTime: 2015-05-15T00:00:19+00:00 ((2457158j,19s,0n),+0s,2299161j)>]] ""略有不同,因为string.Empty会创建一个对象,而""则不会。那个答案对这个问题的投票最多。

然而,this answer表示没有区别。这也是最近的答案。

所以这是在2010年。这是真的吗? string.Emptystring.Empty完全不同,甚至是略有不同吗?

编辑:这个问题是对相关问题的更新,因为我发现令人困惑的是,尽管对此事进行了一些辩论,但没有提出任何现代答案。

3 个答案:

答案 0 :(得分:6)

语言规范(C#4.0)实际上对此主题保持沉默。

根据CLR通过C#,它完全取决于CLR而不是C#编译器。来自p的相关引用。 341:

  

即使程序集指定了此属性/标志[CompilationRelaxations.NoStringInterning],CLR也可以选择实习字符串,但您不应指望这一点。实际上,除非你自己编写的代码明确地调用了String的Intern方法,否则你真的不应该编写依赖于字符串实例的代码。

因此使用""可能会也可能不会创建新的字符串对象。这取决于所使用的CLR(版本)。并且编译器也可能折叠常量,在这种情况下""每个 assembly 编译单元将花费1个对象,而不是每次出现。

这些都不会对内存使用或速度产生任何相关影响,但明确的指导原则应该是避免使用ReferenceEquals(s1, "")ReferenceEquals(s1, String.Empty)

当然,Object.Equals(s1, s2)s1 == s2始终可以正常使用字符串。

答案 1 :(得分:0)

您可以在String.Empty中正确阅读,此字段的值(String.Empty)是零长度字符串,""

您可以通过小测试来测试它们是否引用相同的字符串。

void main()
{
    String first = "";
    String second = String.empty;

    bool test = Object.ReferenceEquals(first, second);
}

Test将返回true,这意味着它们引用同一个对象。

另一个细微差别是,评估""String.empty稍微更优化和有效。

修改

static void Main ( string[] args )
{
    string s1 = "MyTest";
    string s2 = new   StringBuilder().Append("My").Append("Test").ToString();
    string s3 = String.Intern(s2);

    Console.WriteLine((Object)s2 == (Object)s1); // Different references.
    Console.WriteLine((Object)s3 == (Object)s1); // The same reference.
    Console.WriteLine();


    s1 = "";
    s2 = new StringBuilder().Append("").ToString();
    s3 = String.Empty;
    string s4 = String.Intern(s2);

    Console.WriteLine((Object)s2 == (Object)s1); // The same reference.
    Console.WriteLine((Object)s3 == (Object)s1); // The same reference.
    Console.WriteLine((Object)s4 == (Object)s1); // The same reference.
    Console.WriteLine((Object)s4 == (Object)s2); // The same reference.
}

很明显告诉实习生字符串文字已被实习。当stringbuilder创建一个具有相同对象的新String对象时,它不会被实现,并且对该对象的引用也不相同。但是,当我们String.Intern(s2)时,该方法会返回分配给s1的相同引用,然后将引用分配给s3

<强>思想

为什么然后,四个案例都返回true。我知道字符串文字""是固定的,但为什么不使用Stringbuilder""附加到与""相同的新字符串对象,即使从技术上来说也是如此是一个没有实习的新对象。

答案 2 :(得分:-1)

由于有些人已经评论了CLR做什么/不做什么以及对象.RefereceEquals,我将提供两个以上的输入数据。

  1. 表现明智,没有任何重大差异。我用这段代码来测试它:

    示例代码:

    public class StringsTest
    {
    private int i, maxValue = 500000000;
    string myString = "test";
    
    public long CompareToEmptyQuotes()
    {
        Stopwatch sw = Stopwatch.StartNew();
        sw.Start();
    
        for (i = 0; i < maxValue; i++)
        {
            if (myString == "")
            {
                ;
            }
        }
    
        sw.Stop();
        Debug.WriteLine("Elpased Time: {0}", sw.ElapsedMilliseconds);
        return sw.ElapsedMilliseconds;
    }
    
    public long CompareToEmptyString()
    {
        Stopwatch sw = Stopwatch.StartNew();
        sw.Start();
    
        for (i = 0; i < maxValue; i++)
        {
            if (myString == string.Empty)
            {
                ;
            }
        }
    
        sw.Stop();
        Debug.WriteLine("Elpased Time: {0}", sw.ElapsedMilliseconds);
        return sw.ElapsedMilliseconds;
    }
    }
    
  2. 关于生成的代码,这就是MSIL的样子:

  3. 使用&#34;&#34;生成:IL_001e:ldstr&#34;&#34;

    使用string.Empty生成:IL_001e:ldsfld string [mscorlib] System.String :: Empty

    这个问题here扩展了ldstr和ldsfld之间的差异(或相等)。