简体   繁体   English

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

[英]C# performance of struct containing a string vs class containing a string

Please check out these two small examples:请查看这两个小例子:

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

From what I know if I pass struct as a parameter it will make a copy of it someObject.Method(this.cachedStruct);据我所知,如果我将 struct 作为参数传递,它会复制它someObject.Method(this.cachedStruct); - which in turn will make a copy of a StringValue as string s are immutable it will allocate array in memory for this string which is quite costly operation [pardon me if I made a mistake, please correct me in such a case]. - 这反过来会复制一个StringValue因为string s 是不可变的,它将在内存中为此字符串分配数组,这是非常昂贵的操作 [请原谅我犯了错误,在这种情况下请纠正我]。

So in this instance I assume it will be faster to use instances of the Class rather than copying StringValue each time.因此,在这种情况下,我认为使用Class实例而不是每次都复制StringValue会更快。 QUESTION: Are my assumptions correct and Class is a better choice for this kind of a situation or is it still more beneficial and faster to use Struct ?问题:我的假设是否正确并且Class是这种情况的更好选择,还是使用Struct更有利、更快?

Since String and string are the same.因为Stringstring是相同的。 ref - What is the difference between String and string in C#? ref - C# 中的字符串和字符串有什么区别? . . I cannot use String in struct to prevent it from creating a new string object when struct has been passed as a parameter.当 struct 作为参数传递时,我不能在 struct 中使用String来防止它创建新的string对象。

To better address the issue, here is another example.为了更好地解决这个问题,这里是另一个例子。 Sorry if it's a bit rough example.对不起,如果这是一个粗略的例子。

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

My understanding is that if I use Struct without changing string value it will still allocate memory for StringValue each time I pass it as a parameter.我的理解是,如果我在不更改string值的情况下使用Struct ,则每次将其作为参数传递时,它仍会为StringValue分配内存。 While when using Class and passing its instance as a parameter - it will pass Class instance as a reference type without copying values, thus not allocating any memory for StringValue .而当使用Class并将其实例作为参数传递时 - 它会将Class实例作为引用类型传递而不复制值,因此不会为StringValue分配任何内存。

My question might seem similar to C#, struct vs class, faster?我的问题可能看起来类似于C#,struct vs class,更快? [duplicate] and other questions (I believe I have gone through them all (the ones that struct vs class performance)) but none of them have given me an answer. [重复]和其他问题(我相信我已经完成了所有问题(结构与课堂表现的问题)),但他们都没有给我答案。

The string is for example at address 0x0110 and called "hello" .例如,该字符串位于地址0x0110并称为"hello" The struct does not store the string itself, it only stores the reference to this string.该结构不存储字符串本身,它只存储对该字符串的引用。 Thus the struct will only store "0x0110" .因此该结构将只存储"0x0110" When you copy the struct, the struct copy will store the same reference "0x0110" .当您复制结构时,结构副本将存储相同的引用"0x0110" Not the string, just the reference.不是字符串,只是引用。 No new string object will be created.不会创建新的字符串对象。 But when you change the string in the struct copy, for example from "hello" to "bla" , a new string will be created at a new address.但是,当您更改结构副本中的字符串时,例如从"hello"更改为"bla" ,将在新地址处创建一个新字符串。 For example "bla" will be at address 0x0220 .例如, “bla”将位于地址0x0220 处 the struct copy will then store "0x0220" instead of "0x0110" .然后结构体副本将存储"0x0220"而不是"0x0110" The original struct will still store "0x0110" .原始结构仍将存储"0x0110" You are now having 2 strings in memory at different adresses.您现在在不同地址的内存中有 2 个字符串。

0x0110 "hello" 0x0110 “你好”
0x0220 "bla" 0x0220 “bla”

PS: that is a simplification of what really happens. PS:这是对真正发生的事情的简化。

You seem to not know exactly how reference and value types work.您似乎不太清楚引用类型是如何工作的。

You have variable a of a type that is either class or a struct.您有一个类型为类或结构的变量a This variable holds a value , thats all a variable is.这个变量保存一个,这就是变量的全部。 What the value is depends one whether the type is a reference type or a value type:值是什么取决于类型是引用类型还是值类型:

  • If its a reference type, the value of a is a reference , that is, a memory address where the referenced object is found.如果它的引用类型,值a基准,即,其中被引用的对象被发现的存储器地址。
  • If its a value type, the value of a is the value type itself.如果是值类型,则a的值就是值类型本身。

In C#, by default, variables are passed by value.在 C# 中,默认情况下,变量是按值传递的。 That is, a copy of the variable's value is made:也就是说,创建了变量值副本

SomeType a = new SomeType();
var b = a;
SomeMethod(b)

void SomeMethod(SomeType t) { }

b holds a copy of a . b持有的副本a And t holds a copy of b .并且t持有b的副本。

If SomeType is a reference type (for example string ) then all three variables a , b and t hold the same value;如果SomeType是引用类型(例如string ),则所有三个变量abt保持相同的值; an address to the string instance originally assigned to a .最初分配给a的字符串实例的地址。

If SomeType is a value type, then all three variables hold three identical but distinct instances of the value type returned by new SomeType() .如果SomeType是值类型,则所有三个变量都包含new SomeType()返回的值类型的三个相同但不同的实例。 The variables that make up the inner state of said value type are themselves copied in the same manner: their value is copied.构成所述值类型的内部状态的变量本身以相同的方式被复制:它们的被复制。

Does that make it clearer?这样说清楚了吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM