C# 这是什么;钉住控制柄对象[]”;当我使用列表时在Jetbrains dotMemory中看到的<;T>;?
我试图用最简单的代码来重现我所看到的。下面是完整的程序,但我将在这里描述它。假设我有一个名为C# 这是什么;钉住控制柄对象[]”;当我使用列表时在Jetbrains dotMemory中看到的<;T>;?,c#,.net,memory-management,C#,.net,Memory Management,我试图用最简单的代码来重现我所看到的。下面是完整的程序,但我将在这里描述它。假设我有一个名为ListData的类,它只有一些属性。然后假设我有一个MyList类,它有一个成员List m\u List。假设m_list在MyList构造函数中初始化 在main方法中,我只需创建一个MyList对象,向其中添加一些ListData,然后让它超出范围。添加ListData后,我在dotMemory中拍摄快照,然后在MyList对象超出范围后拍摄另一个快照 在dotMemory中,我可以看到MyLis
ListData
的类,它只有一些属性。然后假设我有一个MyList
类,它有一个成员List m\u List
。假设m_list
在MyList
构造函数中初始化
在main方法中,我只需创建一个MyList
对象,向其中添加一些ListData
,然后让它超出范围。添加ListData
后,我在dotMemory中拍摄快照,然后在MyList
对象超出范围后拍摄另一个快照
在dotMemory中,我可以看到MyList
对象已按预期回收。我还看到,我创建的两个ListData
对象也按照预期得到了回收
我不明白的是,为什么有一个ListData[]
幸存了下来?
以下是此项目的屏幕截图:
我在最新的快照上为ListData[]
打开幸存的对象,然后查看密钥保留路径,这就是我看到的
我不熟悉.NET内存管理,我创建了这个示例应用程序来帮助我探索它。我下载了JetBrains dotMemory 4.3版的试用版。我正在使用Visual Studio 2013 Professional。我必须学习内存管理,这样才能解决工作中的内存问题
这里是完整的程序,可以用来重现这一点。这只是一个快速而肮脏的应用程序,但如果你对它进行分析,它会得到我想要的东西
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class ListData
{
public ListData(string name, int n) { Name = name; Num = n; }
public string Name { get; private set; }
public int Num { get; private set; }
}
class MyList
{
public MyList()
{
m = new List<ListData>();
}
public void AddString(ListData d)
{
m.Add(d);
}
private List<ListData> m;
}
class Program
{
static void Main(string[] args)
{
{
MyList l = new MyList();
bool bRunning = true;
while (bRunning)
{
Console.WriteLine("a or q");
string input = Console.ReadLine();
switch (input)
{
case "a":
{
Console.WriteLine("Name: ");
string strName = Console.ReadLine();
Console.WriteLine("Num: ");
string strNum = Console.ReadLine();
l.AddString(new ListData(strName, Convert.ToInt32(strNum)));
break;
}
case "q":
{
bRunning = false;
break;
}
}
}
}
Console.WriteLine("good bye");
Console.ReadLine();
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
命名空间控制台应用程序1
{
类列表数据
{
公共ListData(字符串名,int n){name=name;Num=n;}
公共字符串名称{get;private set;}
public int Num{get;private set;}
}
类MyList
{
公共MyList()
{
m=新列表();
}
公共void AddString(ListData d)
{
m、 加(d);
}
私人名单m;
}
班级计划
{
静态void Main(字符串[]参数)
{
{
MyList l=新的MyList();
布尔·布伦宁=真;
当(布伦宁)
{
控制台写入线(“a或q”);
字符串输入=Console.ReadLine();
开关(输入)
{
案例“a”:
{
Console.WriteLine(“名称:”);
字符串strName=Console.ReadLine();
控制台。WriteLine(“Num:”);
字符串strNum=Console.ReadLine();
l、 AddString(新列表数据(strName,Convert.ToInt32(strNum));
打破
}
案例“q”:
{
布鲁宁=假;
打破
}
}
}
}
Console.WriteLine(“再见”);
Console.ReadLine();
}
}
}
步骤:
ListData[0]
实例是通过List
的静态构造函数创建的,您将看到:
static readonly T[] _emptyArray = new T[0];
List
初始化一个默认的空数组,以便在每次创建一个新的List
时避免这样的分配。这是默认构造函数:
public List()
{
_items = _emptyArray;
}
只有一个您使用的List.Add
,它将调整数组的大小
static
成员从引用,在应用程序中为每个AppDomain
创建一次。您看到的固定的对象[]
实际上是存储所有静态
实例的位置
由于实例是静态的,它将在应用程序的生命周期内一直保留在内存中。Yuval,感谢您的回复。我正在查看您的答案,以便理解,如果我有问题,我会让您知道。为了确保我理解正确,请允许我用自己的话解释,如果我错了,请纠正我。我看到的是静态的空射线被抛在了后面。由于_emptyArray是静态的,它将始终是空数组的根,因此它永远不会被垃圾收集