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

我正在尝试使用一个定制的链表类,并在我的一个C#程序中使用一个枚举器。我不想显示太多的代码,希望这就足够了

我不确定,但这就是统计员应该看起来的样子吗

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()模式。虽然我的假设有误,但我同意你的看法。仅供参考,可能与本问答相关,也可能与本问答无关,但以下是一个问答,比较迭代器块的使用情况,以选择: