请查看以下两个小示例:
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
更有益和更快?
因为String
和string
相同。参考-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]和其他问题(我相信我已经遍历了所有问题(有关结构与班级表现的问题)),但没有一个给我答案。
例如,该字符串位于地址0x0110处,称为“ hello”。该结构本身不存储字符串,它仅存储对该字符串的引用。因此,该结构将仅存储“ 0x0110”。复制该结构时,该结构副本将存储相同的引用“ 0x0110”。不是字符串,只是引用。不会创建新的字符串对象。但是,当您将结构副本中的字符串从“ hello”更改为“ bla”时。一个新的字符串将被创建在一个新的地址。例如,“ bla”将位于地址0x0220。然后,该结构副本将存储“ 0x0220”而不是“ 0x0110”。原始结构仍将存储“ 0x0110”。您现在将在内存中以不同的地址存储2个字符串。
PS:这是实际情况的简化。
您似乎不太清楚reference和value类型如何工作。
您具有类型为类或结构的变量a
。该变量保存一个value,这就是所有变量。值是什么取决于类型是引用类型还是值类型:
a
的值为引用,即在其中找到引用对象的内存地址。a
的值就是值类型本身。在C#中,默认情况下,变量按值传递。也就是说,创建了一个[[变量值的副本]:SomeType a = new SomeType();
var b = a;
SomeMethod(b)
void SomeMethod(SomeType t) { }
。b
持有a
的副本
t
拥有b
的副本。如果SomeType
是引用类型(例如string
),则所有三个变量a
,b
和t
都具有相同的值;最初分配给a
的字符串实例的地址。如果SomeType
是值类型,则所有三个变量都包含new SomeType()
返回的值类型的三个
相同但不同
实例。构成所述值类型的内部状态的变量本身以相同的方式被复制:它们的value被复制。是否更清楚?