包含字符串的结构与包含字符串的类的 C# 性能

Can*_*ax_ 2 c# string heap performance cil

请查看这两个小例子:

public struct Struct
{
    public readonly string StringValue;
    public readonly int IntValue;

    public Struct(string stringValue)
    {
        this.StringValue = stringValue;
        this.IntValue = this.StringValue.GetHashCode(); // Just ignore this assignment, please :).
    }
}

public class Class
{
    public readonly string StringValue;
    public readonly int IntValue;

    public Class(string stringValue)
    {
        this.StringValue = stringValue;
        this.IntValue = this.StringValue.GetHashCode(); // Just ignore this assignment, please :).
    }
}
Run Code Online (Sandbox Code Playgroud)

据我所知,如果我将 struct 作为参数传递,它将制作它的副本someObject.Method(this.cachedStruct);- 这反过来将制作 a 的副本,StringValue因为strings 是不可变的,它将在内存中为该字符串分配数组,这是非常昂贵的操作 [请原谅我,如果我犯了一个错误,请在这种情况下纠正我]。

因此,在这种情况下,我认为使用 的实例Class而不是StringValue每次都复制会更快。问题:我的假设是否正确,Class是这种情况的更好选择,还是使用起来更有利、更快捷Struct

因为Stringstring是一样的。ref - C# 中的字符串和字符串有什么区别?. 当 struct 作为参数传递时,我不能使用Stringin struct 来阻止它创建新string对象。

为了更好地解决这个问题,这里是另一个例子。对不起,如果这是一个有点粗糙的例子。

public struct Struct
{
    public string StringValue;
    public int IntValue;

    public Struct(string stringValue)
    {
        this.StringValue = stringValue;
        this.IntValue = this.StringValue.GetHashCode(); // Just ignore this assignment, please :).
    }
}

public class Class
{
    public string StringValue;
    public int IntValue;

    private Struct _niceStruct;

    public void Accept(Struct someStruct)
    {
        someStruct.StringValue = "Something new"; // In this case even if I don't change the value, it was already allocated.
        // Because of copying of struct when it was passed as a parameter.

        Console.WriteLine(this._niceStruct.StringValue); // "Something new".
    }

    public Class(string stringValue)
    {
        this.StringValue = stringValue;
        this.IntValue = this.StringValue.GetHashCode(); // Just ignore this assignment, please :).

        this._niceStruct = new Struct("Old value");

        this.Accept(this._niceStruct);

        Console.WriteLine(this._niceStruct.StringValue); // "Old value".

        // String value was left unaffected.
        // Which [even in the case I wouldn't change the value in the method] means that a new `string` object was allocated when a copy of `Struct` was created.
        // When using `Class` in the same manner - it would change the `string`.
        // New `string` object won't be allocated if value is unchanged.

        // I assume that `string` allocation might be more costly than `Class` allocation in this instance.
    }
}
Run Code Online (Sandbox Code Playgroud)

我的理解是,如果我在Struct不更改string值的情况下使用它,它仍然会为StringValue每次我将它作为参数传递时分配内存。当使用Class和传递它的实例作为参数时 - 它会将Class实例作为引用类型传递而不复制值,因此不会为StringValue.

我的问题可能看起来类似于C#,struct vs class,更快?[重复]和其他问题(我相信我已经完成了所有问题(结构与课堂表现的问题)),但他们都没有给我答案。

Ble*_*ose 5

例如,该字符串位于地址0x0110并称为"hello"。该结构不存储字符串本身,它只存储对该字符串的引用。因此该结构将只存储"0x0110"。当您复制结构时,结构副本将存储相同的引用"0x0110"。不是字符串,只是引用。不会创建新的字符串对象。但是,当您更改结构副本中的字符串时,例如从"hello"更改为"bla",将在新地址处创建一个新字符串。例如,“bla”将位于地址0x0220 处。然后结构副本将存储“0x0220”. 原始结构仍将存储"0x0110"。您现在在不同地址的内存中有 2 个字符串。

0x0110 “你好”
0x0220 “bla”

PS:这是对真正发生的事情的简化。