用范型实现链表代码理解
在《CLR VIa C#》第三版 249页有这样一个例子:利用范型实现简单的链表,代码如下:
public class Node<T>
{
public T _data;
public Node<T> _next;
public Node(T data) : this(data,null) { }
public Node(T data,Node<T> next){
this._data = data;
this._next = next;
}
public override string ToString()
{
return _data.ToString() + (_next != null ? _next.ToString() : null);
}
}
public class LeaderFunction
{
public void function()
{
Node<char> head = new Node<char>('A');
head = new Node<char>('B', head);
head = new Node<char>('C', head);
head = new Node<char>('D', head);
head = new Node<char>('E', head);
Console.WriteLine(head.ToString());
}
}
执行结果是:EDCBA
一开始有点小郁闷:为啥呢?看官请看:head = new Node<char>('B', head);
这句话的意思就是,head重新定向,data=B,next指向上一个head。问题来了,你这个head是一个Node类型,当前的head指向新的node,node中的next指向上一个head,有点小乱,但归根结底问题就是,上个head都被别人抢走了,你还指向毛上个head
想了一会,联想到之前的拆箱和装箱规则,顿时豁然开朗
画个图,其实就明白了

虽然head指向了新的对象,但是原有对象在堆中并没有gc掉,仍让保存则托管堆某块内存中,这个地址保存在每个next中。这样上面的疑问就不存在了!
我们可以麻烦点,不要让堆中的对象处于悬浮状态,我们神明栈中的实例去指向他。就是这样

代码如下:
public class Node<T>
{
public T _data;
public Node<T> _next;
public Node(T data) : this(data,null) { }
public Node(T data,Node<T> next){
this._data = data;
this._next = next;
}
public override string ToString()
{
return _data.ToString() + (_next != null ? _next.ToString() : null);
}
}
public class LeaderFunction
{
public void function()
{
Node<char> head = new Node<char>('A');
Node<char> head1 = new Node<char>('B', head);
Node<char> head2 = new Node<char>('C', head1);
Node<char> head3 = new Node<char>('D', head2);
Node<char> head4 = new Node<char>('E', head3);
Console.WriteLine(head4.ToString());
}
}
其实两种代码写法,对应两种堆,和堆栈的分配方式。但是第一种分配方式显然要简单的多!

浙公网安备 33010602011771号