C# 列表<;类别>;新类占用内存?我是否需要C=null;在代码中?

C# 列表<;类别>;新类占用内存?我是否需要C=null;在代码中?,c#,asp.net,C#,Asp.net,列出新类占用的内存 我是否需要C=null;在下面的代码中 //class Category public List<Category> SelectAll() { List<Category> LV = new List<Category>(); string command = "SELECT * from categories"; SqlCommand sc = new SqlCommand(command, new SqlConnect

列出新类占用的内存

我是否需要C=null;在下面的代码中

//class Category
public List<Category> SelectAll()
{
  List<Category> LV = new List<Category>();  
  string command = "SELECT * from categories";
  SqlCommand sc = new SqlCommand(command, new SqlConnection(GlobalFunction.Function.GetConnectionString()));
  sc.Connection.Open();
  SqlDataReader dr = sc.ExecuteReader();

  using(dr)
  {
    while (dr.Read())
    {

      // My Question is does this cause a memory problem...
      Category C = new Category(); 

      C.CategoryID = Convert.ToInt32(dr["CategoryID"]);
      C.Name = dr["Name"].ToString();
      C.DisplayOrder=Convert.ToInt32(dr["DisplayOrder"]);

      LV.Add(C);

      // I was told to add this because if not it would cause a memory leak.
      C=Null;                                            

    }
  }
  sc.Connection.Close();
  return LV;
}

GridView1.DataSource = List<Category>; 
GridView1.AllowPaging = true;
GridView1.PageSize = 5;
GridView1.DataBind();
//类别
公共列表SelectAll()
{
List LV=新列表();
string命令=“从类别中选择*”;
SqlCommand sc=newsqlcommand(command,newsqlconnection(GlobalFunction.Function.GetConnectionString());
sc.Connection.Open();
SqlDataReader dr=sc.ExecuteReader();
使用(dr)
{
while(dr.Read())
{
//我的问题是这是否会导致记忆问题。。。
类别C=新类别();
C.CategoryID=转换为32(dr[“CategoryID”);
C.Name=dr[“Name”].ToString();
C.DisplayOrder=Convert.ToInt32(dr[“DisplayOrder”]);
LV.添加(C);
//我被告知要添加此项,因为如果不添加,将导致内存泄漏。
C=零;
}
}
sc.Connection.Close();
返回LV;
}
GridView1.DataSource=列表;
GridView1.AllowPaging=true;
GridView1.PageSize=5;
GridView1.DataBind();

否,不需要显式地将C设置为null


垃圾收集器通过查看对象是否有任何未完成的引用来确定是否可以释放该对象。一旦函数SelectAll返回,对该对象的唯一引用应该是LV中的LV.Add(C)。超出范围的堆栈变量将不会导致额外引用,并且不需要设置为null。

C将在函数返回时超出范围,并且有资格进行垃圾收集,因此,不,您不应该在退出之前将C设置为null

现在,如果C有一些系统资源作为成员变量,例如文件、线程或其他一些您希望尽快释放的有限资源,那么它应该实现IDisposable,在这种情况下,您可以执行以下操作

using (Category c = new Category())
{
    // Do stuff here 
}

这将迫使Dispose在using块的末尾被调用。

不,不需要将引用设置为null,这只是不必要的代码,它会占用CPU时间并使代码混乱

不过,代码中还有另一个问题。您只创建了类的一个实例,可以对每个项重用该实例。当您将这些值放入同一个对象时,它们将覆盖以前的值,并最终得到一个列表,其中包含对单个对象的全部引用

此外,您正在为每个迭代创建一个新的列表实例,因此您将丢弃以前的列表,并最终得到一个仅包含最后一项的列表

您需要在循环外部创建列表,并在循环内部创建对象的新实例:

...
SqlDataReader dr = sc.ExecuteReader();

List<Category> LV = new List<Category>();          

using(dr) {
  while (dr.Read()) {

    Category C = new Category();

    C.CategoryID = Convert.ToInt32(dr["CategoryID"]);
    C.Name = dr["Name"].ToString();
    C.DisplayOrder=Convert.ToInt32(dr["DisplayOrder"]);

    LV.Add(C);

  }
}
sc.Connection.Close();
return LV;
。。。
SqlDataReader dr=sc.ExecuteReader();
List LV=新列表();
使用(dr){
while(dr.Read()){
类别C=新类别();
C.CategoryID=转换为32(dr[“CategoryID”);
C.Name=dr[“Name”].ToString();
C.DisplayOrder=Convert.ToInt32(dr[“DisplayOrder”]);
LV.添加(C);
}
}
sc.Connection.Close();
返回LV;

不,不需要显式地将C设置为null

但我不认为代码做了你认为它做的事情。将
C
创建为新的
类别
实例,然后遍历从数据库返回的记录,在
C
上设置属性,然后将其添加到
列表

问题是,您只创建一个
类别
对象,
C
,并在
LV
列表中填充对该相同对象的引用。由于每次通过循环都会对对象
C
进行变异,因此在循环结束时,列表中将有
n
引用,其中
n
SqlDataReader
中返回的行数,但所有
n
引用都将指向同一对象,将根据最后处理的记录设置其属性

因此,一个更简单的答案是:只需移动行
C=newcategory()内部
while(dr.Read())
循环

另外,作为旁注,您可能需要研究一下,这将使您在这里尝试做的事情更加容易。

简言之,不

有人认为您需要这样做的原因是,在较低级别的语言中,如(语言)C,您必须在使用完内存后释放内存。您正在使用更高级别的语言处理垃圾收集。GC跟踪对特定内存段的引用数量,当没有剩余的引用时,自动取消分配

由于LV.Add(C),我相信(Category对象)C最终会保持在这个函数之外,但是稍后,当所有引用都消失时,它会被处理掉


因此,有些情况下你确实需要采取行动,但这些是例外,而不是规则。有关这些异常的详细信息,请参阅他的帖子。

FYI,这段代码似乎有问题-您在循环结束时将C设置为null,然后在下一次迭代中为其成员赋值,这将导致NullReferenceException。感谢我编辑了代码,因为我在重新键入代码时移错了行。谢谢,我想我不需要设置C=null;这是主要问题。我在我的真实代码中修复了这个bug。但是,谢谢。由于LV.Add(C);,是否仍然有对C的引用;?并不是说这会导致内存泄漏,只是说C将持续超过这个函数。