包含字符串的结构与包含字符串的 class 的性能
Performance of struct containing a string vs class containing a string
请查看这两个小示例:
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
s是不可变的,它会在内存中为这个字符串分配数组,这是相当昂贵的操作[如果我犯了错误,请原谅我,在这种情况下请纠正我]。
所以在这种情况下,我认为使用 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.
}
}
我的理解是,如果我在不更改 string
值的情况下使用 Struct
,每次我将其作为参数传递时,它仍会为 StringValue
分配内存。当使用 Class
并将其实例作为参数传递时 - 它会将 Class
实例作为引用类型传递而不复制值,因此不会为 StringValue
.
分配任何内存
我的问题可能看起来类似于 C#, struct vs class, faster? [duplicate] 和其他问题(我相信我已经完成了所有这些问题(结构与 class 性能的问题))但是 none已经给了我答案。
您似乎不完全了解 reference 和 value 类型的工作原理。
您有 a
类型的变量 class 或结构。这个变量持有一个值,这就是一个变量的全部。值是什么取决于类型是引用类型还是值类型:
- 如果是引用类型,
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 被复制。
这样是不是更清楚了?
例如,字符串位于地址 0x0110 并称为 "hello"。该结构不存储字符串本身,它只存储对该字符串的引用。因此该结构将只存储 "0x0110"。当您复制结构时,结构副本将存储相同的引用 "0x0110"。不是字符串,只是参考。不会创建新的字符串对象。但是,当您更改结构副本中的字符串时,例如从 "hello" 更改为 "bla",一个新字符串将在新地址创建。例如 "bla" 将位于地址 0x0220。然后结构副本将存储 "0x0220" 而不是 "0x0110"。原始结构仍将存储 "0x0110"。您现在在不同地址的内存中有 2 个字符串。
0x0110 "hello"
0x0220"bla"
PS:这是对真实情况的简化。
请查看这两个小示例:
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
s是不可变的,它会在内存中为这个字符串分配数组,这是相当昂贵的操作[如果我犯了错误,请原谅我,在这种情况下请纠正我]。
所以在这种情况下,我认为使用 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.
}
}
我的理解是,如果我在不更改 string
值的情况下使用 Struct
,每次我将其作为参数传递时,它仍会为 StringValue
分配内存。当使用 Class
并将其实例作为参数传递时 - 它会将 Class
实例作为引用类型传递而不复制值,因此不会为 StringValue
.
我的问题可能看起来类似于 C#, struct vs class, faster? [duplicate] 和其他问题(我相信我已经完成了所有这些问题(结构与 class 性能的问题))但是 none已经给了我答案。
您似乎不完全了解 reference 和 value 类型的工作原理。
您有 a
类型的变量 class 或结构。这个变量持有一个值,这就是一个变量的全部。值是什么取决于类型是引用类型还是值类型:
- 如果是引用类型,
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 被复制。
这样是不是更清楚了?
例如,字符串位于地址 0x0110 并称为 "hello"。该结构不存储字符串本身,它只存储对该字符串的引用。因此该结构将只存储 "0x0110"。当您复制结构时,结构副本将存储相同的引用 "0x0110"。不是字符串,只是参考。不会创建新的字符串对象。但是,当您更改结构副本中的字符串时,例如从 "hello" 更改为 "bla",一个新字符串将在新地址创建。例如 "bla" 将位于地址 0x0220。然后结构副本将存储 "0x0220" 而不是 "0x0110"。原始结构仍将存储 "0x0110"。您现在在不同地址的内存中有 2 个字符串。
0x0110 "hello"
0x0220"bla"
PS:这是对真实情况的简化。