【问题标题】:will Substring creates another instance C#?Substring 会创建另一个实例 C# 吗?
【发布时间】:2019-04-30 06:34:22
【问题描述】:

我是 C# 字符串的新手,我对此感到困惑

 Object.referenceEquals 

我正在阅读一些文章,上面写着ReferenceEquals 检查它是否在程序中是否相同实例我正在检查object.ReferenceEquals(s1, s4) 即使它们指向相同的数据,为什么它会出现错误?

string s1 = "akhil";
string s2 = "akhil";

Console.WriteLine(object.ReferenceEquals(s1, s2)); //true
s2 = "akhil jain";
Console.WriteLine(object.ReferenceEquals(s1, s2)); //false
//Console.WriteLine(s1 == s2);
//Console.WriteLine(s1.Equals(s2));

string s3 = "akhil";
//1".Substring(0, 5);
Console.WriteLine(s3+" " +s1);
Console.WriteLine(object.ReferenceEquals(s1,s3)); //true


string s4 = "akhil1".Substring(0, 5);
Console.WriteLine(object.ReferenceEquals(s1, s4)); //confusion false why as s4 data is same as s1

【问题讨论】:

  • 它返回 akhil @Loocid
  • 您有两个字符串对象,它们都具有相同的数据,但它们仍然是独立的对象 - 这就是 ReferenceEquals 返回 false 的原因。 Substring 不会遍历内存来尝试查找具有相同内容的其他字符串对象。
  • 你的声明第一个 object.ReferenceEquals(s1, s2) 应该是假的,那为什么它是真的?
  • 因为 s1 和 s2 引用 same 对象,这是由于字符串文字的工作方式。每次在一个程序中使用 C# 中的相同字符串字面量时,最终都会引用同一个对象。当您调用 Substring 时,情况不是

标签: c# string substring equals


【解决方案1】:

引用是相同的,因为 string literalinternedSubstring 返回一个新字符串和一个新引用,它不会尝试第二次猜测你的参数并检查实习生池

String.Intern(String) Method

公共语言运行时通过维护一个 表,称为实习生池,其中包含对 以编程方式声明或创建的每个唯一文字字符串 你的程序。因此,文本字符串的实例具有 特定值在系统中只存在一次。

例如,如果您将相同的文字字符串分配给多个变量,则运行时会检索对文字的​​相同引用 来自实习生池的字符串并将其分配给每个变量

虽然,无用的事实 3454345.2,自 .Net 2 以来,您已经能够出于各种原因将其关闭

CompilationRelaxations Enum

NoStringInterning 将程序集标记为不需要字符串文本实习。在应用程序域中,常见的 语言运行时为每个唯一字符串创建一个字符串对象 字面意思,而不是制作多个副本。这种行为称为 字符串实习,内部需要构建辅助表 消耗内存资源。

【讨论】:

  • 除了子字符串还有其他方法可以创建新实例吗?
  • @Deepak Jain 每个方法,除非你使用文字,或者实习生方法,或者实习生 IL 代码
【解决方案2】:

实例化两个对象时,引用不相等。 Object.ReferenceEquals 方法因此返回 false。但是,字符串是一种非常特殊的情况。如果在代码中声明一个字符串,CLR 会在一个表中维护它。这称为intern pool。这会导致使用相同值实例化的两个字符串引用内存中的相同对象。这将导致 Object.ReferenceEquals 返回 true。

当您的代码中的某些操作形成了一个字符串时,它不会自动留存到池中。因此,它具有不同的引用,尽管字符串的内容可能相同。这在Object.ReferenceEqualshere的文档的备注中也有说明。

请注意,String.Equals() 方法将返回 true。在 C# 中,您还可以对字符串使用 '==' 运算符。请参阅下面的调整代码。

string s1 = "akhil";
string s2 = "akhil";

Console.WriteLine(s1.Equals(s2)); //true
s2 = "akhil jain";
Console.WriteLine(s1.Equals(s2)); //false

string s3 = "akhil";
Console.WriteLine(s3 + " " + s1);
Console.WriteLine(s1.Equals(s3)); //true

string s4 = "akhil1".Substring(0, 5);
Console.WriteLine(s1.Equals(s4)); //this now returns true as well
Console.WriteLine(s1 == s4);      //so does this

【讨论】:

    【解决方案3】:

    object.ReferenceEquals 的值为 false,因为它检查两个引用是否指向同一个对象。 ReferenceEquals 不检查数据是否相等,但如果两个对象占用相同的内存地址。

    正如 TheGeneral 已经提到的,字符串文字被实习并存储在一个名为实习池的表中。这是为了有效地存储字符串对象。

    当一个字符串字面量分配给多个变量时,它们指向实习池中的同一个地址。因此,您对 object.ReferenceEquals 是正确的。但是当您将其与子字符串进行比较时,已在内存中创建了一个新对象。这会在比较引用时导致错误,因为它们是占用不同内存位置的两个不同对象。

    所有动态创建的字符串,或从外部源读取的字符串都不会被自动实习。

    如果您尝试以下操作,您将得到 object.ReferenceEquals 的 true:

    Console.WriteLine(object.ReferenceEquals(s1, string.Intern(s4)));
    

    您可以使用原始数据类型检查 ReferenceEquals 是否返回 false,即使将一个变量分配给另一个变量也是如此。

    int a = 10;
    int b = a;
    Console.WriteLine(ReferenceEquals(a, b)); //false
    

    这是因为每个原始类型都是单独存储的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-24
      • 1970-01-01
      • 2020-02-25
      • 2016-02-01
      • 2023-04-02
      • 2023-03-23
      相关资源
      最近更新 更多