C# 写的一颗树,(不知有没有内存卸漏?)

hetengfei_ 2013-01-23 05:53:00
请大侠指出下面的代码有没有问题!
主要是删除节点时内存会不会有卸漏?


//节点数据//
public class TreeContainerNode
{

object data;
TreeContainerNode parent;
List<TreeContainerNode> childrens;

public object Data
{
get { return data; }
set { data = value; }
}
public TreeContainerNode Parent
{
get { return parent; }
set { parent = value; }
}
public List<TreeContainerNode> Childrens
{
get { return childrens; }
set { childrens = value; }
}

public TreeContainerNode(object data, TreeContainerNode parentNode, List<TreeContainerNode> children)
{
this.data = data;
this.parent = parentNode;
this.childrens = children;
}


}
//树型容器,树型 数据结构
public class TreeContainer
{
//
TreeContainerNode headNode;

public TreeContainerNode HeadNode
{
get { return headNode; }
set { headNode = value; }
}
//指针//
private TreeContainerNode current;//当前节点
//构造 器
public TreeContainer(object data)
{
this.headNode = new TreeContainerNode(data, null, null);
this.current = this.headNode;
}
//移到上一节点
public bool MoveToParent()
{
if (current.Parent == null)
{
return false;
}
else
{
this.current = this.current.Parent;//移动
return true;
}
}
//移到子节点
///添
public bool MoveToChildren(int index)
{
if (this.current.Childrens == null)//没有子节点
{
return false;
}
if (this.current.Childrens.Count <= index)//没有这么多子节点
{
return false;
}
else
{
this.current = this.current.Childrens[index];
}
}
//添加子节点
public bool AddChildrenNode(object data)
{
//设为头节点
if (this.headNode == null)
{
this.headNode = new TreeContainerNode(data, null, null);
return false;
}
else
{
if (this.current.Childrens == null)//表示没有子节点
{
//创建子节点的容器
this.current.Childrens = new List<TreeContainerNode>();
//添加子节点数据
this.current.Childrens.Add(new TreeContainerNode(data, this.current, null));
}
else//表示 有字节点
{
this.current.Childrens.Add(new TreeContainerNode(data, this.current, null));
}
return true;
}
}
///删
//删除当前节点
public bool DeleteCurrentNode()
{
//没有父节点 当前节点就是根节点
//不能删除跟节点
//要删除,可以销毁本对象
if (this.current.Parent == null)
{
return false;
}
else
{
//删除并移到父节点
//记录
TreeContainerNode nodeRecord = this.current.Parent;
//删除
this.current = null;
GC.Collect();//回收!
//还原
this.current = nodeRecord;//
}
}
//册除对象的子节点
public bool DeleteChildrens()
{
if (this.current.Childrens == null)
{
return false;
}
else
{
//不知这样是否会有内存泄漏,因为他的字节点可能来用字节点!
this.current.Childrens == null;
GC.Collect();
return true;
}
}
///改
public bool AlterCurrentData(object data)
{
//正常情况下,不会执行下面的代码
if (this.current == null)
{
return false;
}
//
this.current.Data = null;
GC.Collect();
this.current.Data = data;
return true;
}
///查
//查当前指针指向的数据
public object GetCurrentData()
{
if (this.current == null)
{
return null;
}
return this.current.Data;
}
//查当前字节点的数据
public List<object> GetChildrenData()
{
if (this.current.Childrens == null || this.current.Childrens.Count <= 0)
{
return null;
}
else
{
List<object> data = new List<object>();
foreach (TreeContainerNode node in this.current.Childrens)
{
data.Add(node.Data);
}
return data;
}
}
}


...全文
200 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
qldsrx 2013-01-24
  • 打赏
  • 举报
回复
引用 6 楼 hetengfei_ 的回复:
还有一个问题! 现在我有一个引用, 他指向[对象A], 对于[对象A]来说,可能在其它地方, 还有其它引用指向他, 问题,是我不知道在哪里还有引用指向[对象A], 现在,我想删除对象A ,并回收他的内存, 因为暂时用不到,等用到了再重新加载! (假如 此对象特大,例如他存放的是图片类型的数据--一些图片变换后的数据) 请问: 这该怎么办?
可以这么办,自定义类的时候,继承IDispose接口,重写Dispose方法,里面对内部的图片对象Dispose下,这样当这个自定义的类对象无任何引用时,系统就会在某个时刻(内存不足或空闲时或GC强制回收时),回收这个对象,回收时自动调用你重写的Dispose方法,进而释放图片对象,保证了非托管资源的准确释放。由于这个“无任何引用时”是系统来判断的,因此你不需要考虑“对于[对象A]来说,可能在其它地方, 还有其它引用指向他”
qldsrx 2013-01-24
  • 打赏
  • 举报
回复
即使节点再多嵌套,将根节点引用去掉,就全部释放了,这就好比你释放某个对象的引用但不需要考虑对象属性,也许对象属性也包含其它引用呢? 但是图片是非托管资源,MSDN上面明确写明了必须调用Dispose并将变量指向null才行,因此如果节点包含了图片,则必须对每个节点的图片对象调用Dispose才行,至于指向null可以不必,因为节点对象本身无引用了,自然会被释放,那么图片对象也会被指向null。
hetengfei_ 2013-01-23
  • 打赏
  • 举报
回复
引用 5 楼 a346729576 的回复:
每次看见LZ的头像,我的狗眼就要瞎一次..
靠,不就是处理过的图片,学过PS的会!   
hetengfei_ 2013-01-23
  • 打赏
  • 举报
回复
然后我查了一下: 就把 DeleteCurrentNode 方法改成下面的。就万事大吉了?

//删除当前节点
public bool DeleteCurrentNode()
{
	//没有父节点 当前节点就是根节点
	//不能删除跟节点
	//要删除,可以销毁本对象
	if (this.current.Parent == null)
	{
		return false;
	}
	else
	{
		//删除并移到父节点
		//记录
		TreeContainerNode nodeRecord = this.current.Parent;
		//删除 --把 父节点 对此对象的引用 打断
		for (int i = 0;i<this.current.Parent.Childrens.Count;i++)// eachChildrenNode in this.current.Parent.Childrens)
		{ 
			//他的父节点的子节点集合中的一个 是不是引用了我要删除的对象?
			if (Object.ReferenceEquals(this.current.Parent.Childrens[i], this.current))
			{
				this.current.Parent.Childrens.RemoveAt(i);
			}
		}
		//this.current = null;
		//GC.Collect();//回收!
		//还原
		this.current = nodeRecord;//
	}
}
还有一个问题! 现在我有一个引用, 他指向[对象A], 对于[对象A]来说,可能在其它地方, 还有其它引用指向他, 问题,是我不知道在哪里还有引用指向[对象A], 现在,我想删除对象A ,并回收他的内存, 因为暂时用不到,等用到了再重新加载! (假如 此对象特大,例如他存放的是图片类型的数据--一些图片变换后的数据) 请问: 这该怎么办?
夜色镇歌 2013-01-23
  • 打赏
  • 举报
回复
每次看见LZ的头像,我的狗眼就要瞎一次..
hetengfei_ 2013-01-23
  • 打赏
  • 举报
回复
请问 二楼的大侠, 是这样的, 因为 我删除的时候,是删除当前的节点对象,当节点对象里可能包含着他的子节点对象, 他的子节点对象可能包含着他的孙节点对象, 我就让当前节点对象指向null 是不是就可以让他的子子孙孙都销毁呢? //不过,还有我发现了一个错误, 就是这个类 TreeContainerDeleteCurrentNode 方法,没有让他的parent节点对他引用的变量设为空, (忘记了这个失误. 是不是会造成 ,节点始终删除不掉,而内存卸漏呢?
qldsrx 2013-01-23
  • 打赏
  • 举报
回复
.NET除非引用存在,或者使用了托管资源 修正下: .NET除非引用存在,或者使用了托管资源
qldsrx 2013-01-23
  • 打赏
  • 举报
回复
this.current = null; GC.Collect();//回收! 这2行多余,直接将当前节点修改即可,无需指向null,更不用GC来回收,影响效率的。 .NET除非引用存在,或者使用了托管资源,否则不可能内存泄漏,只要对象引用没了(没有变量指向它),就肯定会被回收的。
嘴哥臭鼬 2013-01-23
  • 打赏
  • 举报
回复

111,098

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧