我有两个问题:
1。界面实施
例如,如果我们使用ArrayList,我们可以看到ArrayList实现了很多接口,其中一个接口是IEnumerable,它有一个抽象方法
IEnumerator GetEnumerator();
如果我们在VS中定义ArrayList,我们可以看到有一个
的方法public virtual IEnumerator GetEnumerator();
但为什么应该有关键字“虚拟”?不应该这个方法在IEnumerable中实现该方法吗?所以方法应该是:
public IEnumerator GetEnumerator();
?
2。链表
我看到了LinkList的一些代码:
LinkedList<Data> myDataList = new LinkedList<Data>();
LinkedListNode<Data> lln;
for (int i = 0; i < 10; i++) //Method 1
{
myData = new Data(i);
lln = myDataList.AddLast(myData);
}
for (int i = 10; i < 20; i++) // Method 2
{
lln = new LinkedListNode<Data>(new Data(i));
myDataList.AddLast(lln);
}
我可以理解方法2,它首先将数据添加到LinkedListNode,而不是将LinkedListNode添加到LinkedList。但是看起来方法1只是直接将数据添加到LinkedList中?这是否意味着如果我们直接将数据添加到LinkedList中,LinkedList将通过向LinkedListNode添加数据来内部创建LinkedListNode,然后将LinkedListNode添加到LinkedList,与方法2相同?
答案 0 :(得分:1)
但为什么应该有关键字“虚拟”?
virtual
关键字允许子类覆盖其实现。没什么好说的。当然你不想要这个简单而明显的答案,你想知道为什么有人会覆盖它。举一个非常简单的例子,假设您创建了自己的GrooveArrayList
,其内部保留了另外两个IEnumerables
(比方说,水果列表和一系列汽车)。如果您将GrooveArrayList
放入foreach语句并开始枚举,会发生什么?它应该迭代水果和汽车吗?按什么顺序?是否应根据某些条件跳过其中一些?如果您的IEnumerable
(在此示例中,GrooveArrayList
)有一些自定义逻辑来迭代,那么您将覆盖此方法并放置该逻辑。我知道这个例子有点荒谬,但这只是为了澄清为什么有人需要覆盖它。实际上我自己并没有这样做,所以......
修改强>
这是ArrayList
的{{1}}实施:
GetEnumerator()
这是否意味着如果我们直接将数据添加到LinkedList中,那么 LinkedList将通过添加数据在内部创建LinkedListNode LinkedListNode然后将LinkedListNode添加到LinkedList,与方法2相同 做?
完全。当您将public virtual IEnumerator GetEnumerator() {
Contract.Ensures(Contract.Result<IEnumerator>() != null);
return new ArrayListEnumeratorSimple(this);
}
直接添加到Data
时,它会在内部为LinkedList
创建LinkedListNode
,将节点添加到其节点,然后返回该创建的节点,以便您可以做你想做的任何事情。
实际上,它们允许您同时执行这两种方式,因此您可以根据具体方案决定使用哪种方式。这有多好?