C# 需要帮助为c中的链表创建枚举器吗#
我正在尝试使用一个定制的链表类,并在我的一个C#程序中使用一个枚举器。我不想显示太多的代码,希望这就足够了 我不确定,但这就是统计员应该看起来的样子吗C# 需要帮助为c中的链表创建枚举器吗#,c#,enumeration,singly-linked-list,C#,Enumeration,Singly Linked List,我正在尝试使用一个定制的链表类,并在我的一个C#程序中使用一个枚举器。我不想显示太多的代码,希望这就足够了 我不确定,但这就是统计员应该看起来的样子吗 class SinglyLinkedListEnumerator<T> : IEnumerator<T> { private Node<E> node; private Node<E> start; public SinglyLinkedListEnumerator(Nod
class SinglyLinkedListEnumerator<T> : IEnumerator<T>
{
private Node<E> node;
private Node<E> start;
public SinglyLinkedListEnumerator(Node<T> node)
{
this.node = node;
start = node;
}
public T Current
{
get { return node.getData(); }
}
public Boolean MoveNext()
{
if (node.getNext() != null)
{
node = node.getNext();
return true;
}
return false;
}
public void Reset()
{
node = start;
}
public void IDisposable.Dispose()
{
}
}
class SingleLinkedListEnumerator:IEnumerator
{
专用节点;
专用节点启动;
公共单链接列表分子(节点)
{
this.node=节点;
开始=节点;
}
公共电流
{
获取{return node.getData();}
}
公共布尔值MoveNext()
{
if(node.getNext()!=null)
{
node=node.getNext();
返回true;
}
返回false;
}
公共无效重置()
{
节点=开始;
}
public void IDisposable.Dispose()
{
}
}
在C#世界中,这个概念被称为枚举而不是迭代。不要与enum
混淆
无论如何,您要查找的相应接口是
System.Collections.Generic
命名空间中的IEnumerable
和IEnumerator
。查看他们的文档,你应该可以开始了。这个概念本身与您在Java中所做的几乎相同。我不知道您的节点的代码是什么样子的,但这看起来很奇怪:
public Boolean MoveNext()
{
if (node.getNext() != null)
{
node = node.getNext();
return true;
}
return false;
}
理想情况下,MoveNext看起来如下所示:
public Boolean MoveNext()
{
// make sure current node is not null
if (node != null)
{
node = node.getNext();
}
// simply return whether current node is null or not
return node != null;
}
public class MyLinkedList : IEnumerable {
Node head = null;
Node current = null;
public IEnumerator GetEnumerator()
{
current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
在初始方法中,将获得下一个节点两次,这可能会导致错误结果。我假设getNext
只返回对当前节点下一个同级节点的引用。否则,我看不到枚举器(或迭代器)类有任何初始问题
为了清楚起见,我将使用currentNode
而不是node
,并将start
更改为startNode
。此外,如果node.getNext()
未返回节点对象,则应重命名该方法以指示它正在执行的操作
我假设node.getNext()
正在移动一个内部引用,但@Servy纠正了我的错误。谢谢
我可能仍然建议更改一些名称以澄清操作。:) 迭代器块使创建实现IEnumerable
的对象变得更加容易:
公共静态IEnumerable迭代(节点根)
{
无功电流=根;
while(当前!=null)
{
收益率返回当前值。getData();
current=current.getNext();
}
}
它删除了大部分样板代码,只允许您定义用于确定序列中的节点的所有逻辑,同时仍然提供编写所有代码的所有功能。linkedlist枚举器应如下所示:
public Boolean MoveNext()
{
// make sure current node is not null
if (node != null)
{
node = node.getNext();
}
// simply return whether current node is null or not
return node != null;
}
public class MyLinkedList : IEnumerable {
Node head = null;
Node current = null;
public IEnumerator GetEnumerator()
{
current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
而节点本身
public class Node
{
public int Data;
public Node Next;
public Node(int value) { Data = value; }
}
对于二叉树您应该实现所有三个:Current、MoveNext和Reset+不要忘记构造函数。我查看了它们的文档,看到了“属性”和方法。我不知道属性意味着什么,这些是必需的方法吗?那么,这是否使常规方法成为可选方法?我仍然很困惑。我是否要将next()方法更改为move()?文档也没有告诉我这些方法应该返回什么,但我可能只是缺少了它。在Java中,有getter和/或setter方法。在C#中,你有属性。关于MoveNext:在C#中,移动到下一个元素并获取是分开的。您有Current
-属性(在Java中是getCurrent()
),您有MoveNext()
,如果它可以前进到下一个元素,而不是返回下一个元素本身,则返回true。我更新了显示我现在拥有的内容的问题,你能告诉我它看起来是否正确吗?请注意,即使在C#中,很多人仍然使用迭代这个术语。使用它并不是完全错误的。请记住,node
本身不是迭代器,而是节点。它的下一个节点是固定的。调用getNext
不会改变节点以更改其下一个节点。虽然您的更改确实让它更干净了,但他的代码没有错。谢谢@Servy。。。似乎可以对OP的代码做出一些假设,但这些假设可能不准确这似乎是一个相当安全的假设。您假设调用GetNext
将更改节点对其下一个节点的内部引用。你的假设依据是什么?我看不到。OP还表示他的代码是有效的,他只是想知道这是否是良好的实践。他指出他的代码是有效的,这使得我的假设非常安全。我的假设是基于这一行:if(node.getNext()!=null)
。我处于Enumerator.MoveNext()模式。虽然我的假设有误,但我同意你的看法。仅供参考,可能与本问答相关,也可能与本问答无关,但以下是一个问答,比较迭代器块的使用情况,以选择: