从 C#9 开始,我不知道有任何方法可以通过引用从通用容器中提取结构,包括List<T>
. 正如杰森奥尔森的回答所说:
真正的根本问题是结构是值类型,而不是引用类型。因此,当您从列表中拉出对结构的“引用”时,它正在创建整个结构的新副本。因此,您对其所做的任何更改都会更改副本,而不是列表中的原始版本。
所以,这可能是非常低效的。SuperCat 的答案,即使它是正确的,通过将更新的结构复制回列表来加剧效率低下。
如果您对最大化结构的性能感兴趣,请使用数组而不是List<T>
. 数组中的索引器返回对结构的引用,并且不像List<T>
索引器那样复制整个结构。此外,数组比List<T>
.
如果您需要随着时间的推移增加数组,那么创建一个类似 的泛型类List<T>
,但在下面使用数组。
有一个替代解决方案。创建一个包含该结构的类并创建公共方法来调用该结构的方法以获得所需的功能。使用 aList<T>
并为 T 指定类。该结构也可以通过 ref 返回方法或 ref 属性返回,该方法返回对该结构的引用。
这种方法的优点是它可以与任何通用数据结构一起使用,例如Dictionary<TKey, TValue>
. 当从 a 中拉出一个结构时Dictionary<TKey, TValue>
,它也会将该结构复制到一个新实例中,就像List<T>
. 我怀疑所有 C# 通用容器都是如此。
代码示例:
public struct Mutable
{
private int _x;
public Mutable(int x)
{
_x = x;
}
public int X => _x; // Property
public void IncrementX() { _x++; }
}
public class MutClass
{
public Mutable Mut;
//
public MutClass()
{
Mut = new Mutable(2);
}
public MutClass(int x)
{
Mut = new Mutable(x);
}
public ref Mutable MutRef => ref Mut; // Property
public ref Mutable GetMutStruct()
{
return ref Mut;
}
}
private static void TestClassList()
{
// This test method shows that a list of a class that holds a struct
// may be used to efficiently obtain the struct by reference.
//
var mcList = new List<MutClass>();
var mClass = new MutClass(1);
mcList.Add(mClass);
ref Mutable mutRef = ref mcList[0].MutRef;
// Increment the x value defined in the struct.
mutRef.IncrementX();
// Now verify that the X values match.
if (mutRef.X != mClass.Mut.X)
Console.Error.WriteLine("TestClassList: Error - the X values do not match.");
else
Console.Error.WriteLine("TestClassList: Success - the X values match!");
}
控制台窗口上的输出:
TestClassList: Success - the X values match!
对于以下行:
ref Mutable mutRef = ref mcList[0].MutRef;
我最初无意中在等号后遗漏了 ref。编译器没有抱怨,但它确实生成了结构的副本,并且在运行时测试失败了。添加 ref 后,它运行正确。