从C#中的列表中获取引用/地址

use*_*746 6 c# collections reference list

我知道C#不处理指针,但我想知道当我知道它的第一个元素时是否可以获得一个列表的引用?例如:假设我有一个定义为的列表

List<T> abc  
Run Code Online (Sandbox Code Playgroud)

如果我有abc [0],我可以获得abc的参考吗?我是C#的新手,如果我的问题看起来很奇怪,我道歉.在C/C++中,我可以使用&abc [0]获取数组abc的地址.当我们知道集合中的一个项目时,C#是否为我们提供了类似的工具,以帮助我们回溯到集合本身?谢谢,

小智 12

从 .NET 5.0 开始,通过使用该System.Runtime.InteropServices.CollectionsMarshal.AsSpan方法,现在可以实现这一点。

如文档所示,在使用范围或从范围中获取的项目引用时,不应将项目添加到列表或从列表中删除。从技术上讲,这也应该扩展为Capacity不应该更改也不应该TrimExcess()调用。如果在主动使用跨度或其引用时使用这些操作,则列表的内部存储器可能不再与跨度中的存储器相同。

// Create a simple list with three items.
var list = new List<int>();
list.Add(123);
list.Add(456);
list.Add(789);

// Print list to console.
Console.WriteLine("List items:");
foreach (var item in list)
    Console.WriteLine(item);
Console.WriteLine();

// Get a reference to the second item in the list.
// WARNING: DO NOT ADD/REMOVE ITEMS FROM THE LIST WHILE USING THIS SPAN
// OR ANY REFERENCES DERIVED FROM THIS SPAN!
var listSpan = CollectionsMarshal.AsSpan(list);
ref var secondItem = ref listSpan[1];
Console.WriteLine($"Referenced value (original): {secondItem}");

// Change the referenced list item.
secondItem = 0;
Console.WriteLine($"Referenced value (modified): {secondItem}");
Console.WriteLine();

// Print the list to console.
Console.WriteLine("List items:");
foreach (var item in list)
    Console.WriteLine(item);
Console.WriteLine();
Run Code Online (Sandbox Code Playgroud)

您应该得到如下输出:

List items:
123
456
789

Referenced value (original): 456
Referenced value (modified): 0

List items:
123
0
789
Run Code Online (Sandbox Code Playgroud)


Jus*_*tin 8

集合在C#中的工作方式与在C++中的工作方式不同,例如,您可以将同一个对象添加到多个不同的集合中,因此要求获取对象的列表引用并不是真的有意义.包含在,因为它可能在许多列表中(或者没有,或者甚至在同一列表中多次)

object myObject = new object();

List<object> list = new List<object>();
list.Add(myObject);

object[] someArray = new object[] { myObject  };
Assert.AreEqual(list[0], someArray[0]);
Run Code Online (Sandbox Code Playgroud)

如果它有帮助你可以把C#中的列表看作指针列表引用存储指针本身对你隐藏的对象,虽然理解实际上实现可能更复杂(并且也无关紧要).

如果列表中的对象与该列表的列表内容之间存在关系,则由您自己明确声明并跟踪该realtionsip的内容,例如通过Parent列表中对象的属性

List<T> myList = new List<T>();

// Whenever an item is added to myList set the Parent property
myList.Add(item);
item.Parent = myList;
Run Code Online (Sandbox Code Playgroud)

这就是Windows Forms为了维护容器中的控件与包含这些控件的容器之间的关系所做的事情.显然,如果有人试图将同一个对象添加到多个列表,您应该决定该怎么做.

  • 我认为.NET中的集合与C++集合的工作方式相同(其中List <T> = std:vector <*T>和LinkedList <T> = std:list <*T>).唯一的区别是,对于引用类型,您只能有指针列表,而std:vector <T>行为仅适用于值类型.不错的答案+1. (3认同)
  • 不它不是.您必须声明一个带有Parent属性的类型. (2认同)