Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.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# 字符串实习_C#_.net_String - Fatal编程技术网

C# 字符串实习

C# 字符串实习,c#,.net,string,C#,.net,String,在下面的代码中,我正在检查对象引用的相等性 string x = "Some Text"; string y = "Some Other Text"; string z = "Some Text"; Console.WriteLine(object.ReferenceEquals(x, y)); // False Console.WriteLine(object.ReferenceEquals(x, z)); // True Console.WriteLine(object.Reference

在下面的代码中,我正在检查对象引用的相等性

string x = "Some Text";
string y = "Some Other Text";
string z = "Some Text";

Console.WriteLine(object.ReferenceEquals(x, y)); // False
Console.WriteLine(object.ReferenceEquals(x, z)); // True
Console.WriteLine(object.ReferenceEquals(y, z)); // False

y = "Some Text";

Console.WriteLine(object.ReferenceEquals(x, y)); // True
Console.WriteLine(object.ReferenceEquals(x, z)); // True
Console.WriteLine(object.ReferenceEquals(y, z)); // True
在这里:

  • x
    z
    指同一对象;我可以说,
    x
    是实习的,而
    z
    是用在这个版本上的。嗯,我对此不确定;如果我错了,请纠正我
  • 我更改了
    y
    的值,将其指定为与x相同的值。我以为它会在这里创造一个新的物体;但我错了,它使用了相同的引用
我的问题是:

  • .net
    是否对我使用的每个字符串都使用
  • 如果是这样的话,会不会影响性能
  • 如果不是,在上面的示例中,引用是如何变得相同的
字符串文本将自动插入

默认情况下,程序创建的字符串将不会被插入(用户输入字符串也不会)

在上面,“Some Text”和“Some Other Text”都被插入了,由于您在这些地方使用了文本,您可以看到插入的版本就是引用的版本

在代码中,如果您有:

string.Format("{0} {1}", "Some", "Text")

您将看到返回的引用与其他文本的引用不同。

是的,编译器中的常量字符串表达式使用
ldstr
处理,这保证了内部(通过):

公共语言基础设施(CLI)保证引用具有相同字符序列的两个元数据令牌的两条ldstr指令的结果返回完全相同的字符串对象(这一过程称为“字符串插入”)

这不是每一个字符串;它是代码中的常量字符串表达式。例如:

string s = "abc" + "def";
int i = GetValue();
string s = "abc" + i;
只有1个字符串表达式-IL将是“abcdef”上的ldstr(编译器可以计算合成的表达式)

这不会影响性能

运行时生成的字符串不会自动插入,例如:

string s = "abc" + "def";
int i = GetValue();
string s = "abc" + i;
在这里,“abc”是实习的,但“abc8”不是。还请注意:

char[] chars = {'a','b','c'};
string s = new string(chars);
string t = "abc";

请注意,
s
t
是不同的引用(文本(分配给
t
)是插入的,但新字符串(分配给
s
)不是插入的)。

我想itz会再次重复

可能重复的

重复

The Common Language Infrastructure (CLI) guarantees that the result of two ldstr instructions referring to two metadata tokens that have the same sequence of characters return precisely the same string object (a process known as "string interning").
net是否对我使用的每个字符串都使用字符串实习生

不,但它确实对编译时知道的字符串使用它,因为它们是代码中的常量

string x = "abc"; //interned
string y = "ab" + "c"; //interned as the same string because the
                       //compiler can work out that it's the same as
                       //y = "abc" at compile time so there's no need
                       //to do that concatenation at run-time. There's
                       //also no need for "ab" or "c" to exist in your
                       //compiled application at all.
string z = new StreamReader(new FileStream(@"C:\myfile.text")).ReadToEnd();
                       //z isn't interned because it isn't known at compile
                       //time. Note that @"C:\myfile.text" is interned because
                       //while we don't have a variable we can access it by
                       //it is a string in the code.
如果是这样的话,会不会影响性能

不,它有助于提高性能:

第一:所有这些字符串都将在应用程序的内存中的某个地方。实习方式 我们没有不必要的拷贝,所以我们使用更少的内存。 第二:它可以进行字符串比较,我们知道这是从实习字符串超快速。 第三:这个数字不多,但它给其他比较带来的推动作用确实如此。考虑在内置比较器之一中存在的代码:

public override int Compare(string x, string y)
{
    if (object.ReferenceEquals(x, y))
    {
        return 0;
    }
    if (x == null)
    {
        return -1;
    }
    if (y == null)
    {
        return 1;
    }
    return this._compareInfo.Compare(x, y, this._ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
}
这适用于排序,但同样适用于相等/不相等检查。要检查两个字符串是否相等或按顺序排列,需要我们执行O(n)运算,其中n与字符串的长度成比例(即使在可以进行一些跳跃和巧妙操作的情况下,它仍然是成比例的)。这对于长字符串来说可能很慢,而比较字符串是很多应用程序经常做的事情——这是提高速度的好地方。对于相等的情况,它也是最慢的(因为当我们发现一个差异时,我们可以返回一个值,但必须完全检查相等的字符串)

即使您重新定义了“equals”的含义(区分大小写、不区分大小写、不同的文化-所有内容仍然等于自身,并且如果您创建了一个
equals()
覆盖,不遵循该覆盖,您将有一个bug)。一切事物总是在它所等于的事物的同一点上排序。这意味着两件事:

我们不必再做任何工作,总是能考虑到自身的平等。
  • 我们总是可以给出一个比较值
    0
    ,用于在不做任何额外工作的情况下将某个东西与自身进行比较
  • 因此,上面的代码可以简化这种情况,而无需进行更复杂、更昂贵的比较。也没有不利的一面,因为如果我们不讨论这种情况,我们就必须为两个值都通过where
    null
    的情况添加一个测试

    现在,某些算法的工作方式经常会自然而然地将某些东西与自身进行比较,所以这总是值得做的。然而,字符串实习增加了两个字符串在不同值(例如,问题开头的
    x
    z
    中)实际上相同的时间,因此增加了捷径对我们有效的频率

    大多数情况下,这只是一个小小的优化,但我们是免费获得的,而且我们经常获得,拥有它真是太棒了。实际的外卖-如果你写的是<代码>等于<代码>或<代码>比较< /代码>考虑你是否也应该使用这个捷径。

    一个相关的问题是“我应该什么都实习吗?”

    这里,我们必须考虑字符串中编译的缺点。在字符串中编译时,实习从来都不是浪费,因为它们必须在某个地方。然而,如果你从一个文件中读取一个字符串,将其插入内存,然后再也不使用它,那么它将存活很长时间,这是浪费。如果你一直这样做,你可能会削弱你的记忆使用

    让我们想象一下,您经常阅读包含一些标识符的一堆条目。您经常使用这些标识符将项目与其他来源的数据进行匹配。有一小部分标识符可以看到(比如说只有几百个可能的值)。因为平等性检查是这些字符串的全部内容,而且没有太多的字符串,所以需要(在数据区域和