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

问题描述 投票:0回答:2

请查看以下两个小示例:

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 :).
    }
}

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

因此,在这种情况下,我认为使用Class的实例比每次复制StringValue更快。问题:我的假设是正确的,Class在这种情况下是更好的选择,还是使用Struct更有益和更快?

因为Stringstring相同。参考-What is the difference between String and string in C#?。我不能在结构中使用String来防止在将结构作为参数传递时创建新的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.
    }
}

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

[我的问题似乎与C#, struct vs class, faster? [duplicate]和其他问题(我相信我已经遍历了所有问题(有关结构与班级表现的问题)),但没有一个给我答案。

c# string performance heap cil
2个回答
1
投票

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

PS:这是实际情况的简化。


0
投票

您似乎不太清楚referencevalue类型如何工作。

您具有类型为类或结构的变量a。该变量保存一个value,这就是所有变量。值是什么取决于类型是引用类型还是值类型:

  • 如果是引用类型,则a的值为引用,即在其中找到引用对象的内存地址。
  • 如果是值类型,则a的值就是值类型本身。

在C#中,默认情况下,变量按值传递。也就是说,创建了一个[[变量值的副本]:SomeType a = new SomeType(); var b = a; SomeMethod(b) void SomeMethod(SomeType t) { }

b持有a

副本

t拥有b的副本。如果SomeType是引用类型(例如string),则所有三个变量abt都具有相同的值;最初分配给a的字符串实例的地址。

如果SomeType是值类型,则所有三个变量都包含new SomeType()返回的值类型的三个

相同但不同

实例。构成所述值类型的内部状态的变量本身以相同的方式被复制:它们的value被复制。
是否更清楚?
© www.soinside.com 2019 - 2024. All rights reserved.