想知道一种在C#中使用List保存内存的方法<&燃气轮机;带结构

想知道一种在C#中使用List保存内存的方法<&燃气轮机;带结构,c#,list,reference,struct,C#,List,Reference,Struct,我甚至不知道该如何表达这个问题。我将一些CustomStruct对象作为参数传递给一个类方法,并将它们存储在一个列表中。我想知道的是,如果CustomStruct找到了一个等价的实例,那么向该实例添加多个引用是否可能更有效 这是一个虚拟/示例结构: public struct CustomStruct { readonly int _x; readonly int _y; readonly int _w; readonly int _h; readonly

我甚至不知道该如何表达这个问题。我将一些CustomStruct对象作为参数传递给一个类方法,并将它们存储在一个列表中。我想知道的是,如果CustomStruct找到了一个等价的实例,那么向该实例添加多个引用是否可能更有效

这是一个虚拟/示例结构:

public struct CustomStruct
{
    readonly int _x;
    readonly int _y;
    readonly int _w;
    readonly int _h;
    readonly Enum _e;
}
使用下面的方法,可以传递一个、两个或三个CustomStruct对象作为参数。在最后一种方法(采用三个参数)中,可能第三个参数和第二个参数的值与第一个参数的值相同

List<CustomStruct> _list;

public void AddBackground(CustomStruct normal)
{
    AddBackground(normal, normal, normal);
}

public void AddBackground(CustomStruct normal, CustomStruct hover)
{
    AddBackground(normal, hover, hover);
}

public void AddBackground(CustomStruct normal, CustomStruct hover, CustomStruct active)
{
    _list = new List<CustomStruct>(3);
    _list.Add(normal);
    _list.Add(hover);
    _list.Add(active);
}
List\u List;
public void AddBackground(CustomStruct normal)
{
AddBackground(正常、正常、正常);
}
public void AddBackground(CustomStruct normal、CustomStruct hover)
{
AddBackground(正常、悬停、悬停);
}
public void AddBackground(CustomStruct普通、CustomStruct悬停、CustomStruct活动)
{
_列表=新列表(3);
_列表。添加(正常);
_列表。添加(悬停);
_列表。添加(活动);
}
现在,我相信该方法将创建CustomStruct对象的新实例,然后将每个对象的引用添加到列表中

我的理解是,如果我改为检查正常悬停之间是否相等,并且(如果相等)再次插入正常代替悬停,当方法完成时,悬停将丢失所有引用并最终被垃圾收集,而normal将在列表中有两个引用。对于活动的也可以这样做

那会更好,对吗?CustomStruct是一个ValueType,因此堆栈上会保留一个实例,三个列表引用只指向它。总体列表大小不是由包含的对象类型决定的,而是由其容量决定的。通过消除“重复的”CustomStuct对象,您可以清理它们

将CustomStruct对象传递给这些方法时,每次都会创建新实例。当结构添加到列表中时,是否制作了另一个副本?例如,如果我只传递一个CustomStruct,AddBackground(normal)将创建原始变量的副本,然后将其传递三次给AddBackground(normal、hover、active)。在这种方法中,原始副本制作三份副本。当使用Add()将三个局部变量添加到列表中时,是否在Add()中创建了其他副本,这是否违背了前面提到的任何相等性检查的目的

有没有更好的方法来处理这个问题?是否应该将结构作为引用传递给方法以避免此问题


我在这里遗漏了什么吗?

请注意,每次您将结构作为参数传递给函数,或将一个变量分配给另一个变量,或在您的情况下,将其添加到列表中,都会创建整个结构的副本(在您的情况下,将复制20个字节)

还要注意,在某些情况下,除了(我认为)结构之外,没有GC引用



如果使用类而不是结构,则只能节省内存—这样可以像您建议的那样测试相等性。

您在同一行中讨论垃圾收集和结构,这没有意义。最终,每次查看结构时,它都可能复制自身。如果要重复使用同一引用,则需要一个类,或者需要将结构包装在一个类中(装箱;内置或手动)

代码中实际发生的情况是:

_list.Add(normal); // a **copy** of normal is set into the list
_list.Add(hover); // a **copy** of hover is set into the list
_list.Add(active); // a **copy** of active is set into the list
当你考虑它时,它(从空间角度)与:

_list.Add(normal); // a **copy** of normal is set into the list
_list.Add(normal); // a **copy** of normal is set into the list
_list.Add(normal); // a **copy** of normal is set into the list

请注意,副本不会进入堆栈(struct=stack是一个常见的神话)。数据进入堆上的数组(在
列表中)。通过引用将结构传递给arount不会对
Add
的行为产生任何影响(在将结构传递给此方法时,它只是避免复制结构,但内存复制速度很快)。

听起来好像你把值类型和引用类型的定义搞混了。Struct是值类型,因此变量存储实际值。结构的实例不是对象,GC不会收集它。引用类型变量存储对实例的引用。实例存储在堆上,并最终由GC收集


结构列表本身就是引用类型,因此它将与其值一起存储在堆中。每次向列表中添加条目时,数据都会从方法中的本地表示复制到列表中的一个插槽中。如果多次存储相同的值,则会将其复制多次。它只是列出一个整数列表。如果将值42重复了十次,则会在列表的内存中找到值42的十个副本

根据定义,值类型没有引用——只有引用类型才有引用。值类型的存储最终在数组本身中。值类型只有在不嵌入其他对象时才在堆栈上。所以对于列表,我总是在内存中有三个CustomStruct对象?如果我多次向列表中添加()相同的ValueType对象,是否每次添加都会在内存中创建一个新对象?是否有证据表明这实际上占用了大量内存?这张单子到底有多大?不是很大,真的。我只是想让事情有效率。还在学这门语言。我感谢你的回答!列表占用的内存与其容量成比例,而不是其当前长度。当列表中有三个CustomStruct时,实际上可能有足够的空间容纳多个CustomStruct,这取决于列表用于增长的算法。但是,是的,当您将“相同”的ValueType对象添加到列表中三次时,您将使用的内存至少是struct.re“我认为”大小的三倍:即使