【问题标题】:singly linked list in c# using extension methodc#中使用扩展方法的单链表
【发布时间】:2019-03-11 16:36:01
【问题描述】:
  1. 为什么扩展方法在插入操作中不返回修改后的节点。
  2. 但在创建链接列表时它工作正常。
  3. 扩展方法应该返回修改后的节点。
  4. 执行此操作的最佳方法是什么。
  5. IS 扩展方法性能好

代码如下

public class Node
{
    public Object Data { get; set; }
    public Node NextNode { get; set; }
}
public static class ListOperations
{
    public static void CreateLinkedList(this Node node, Object data)
    {
        if (node.Data == null)
        {
            node.Data = data;
        }
        else
        {
            Node newnode = new Node();
            newnode.Data = data;
            Node current = new Node();
            current = node;
            while (current.NextNode != null)
            {
                current = current.NextNode;
            }
            current.NextNode = newnode;
            node = current;
        }
    }
    public static void InsertNode(this Node node1, Object data, int position)
    {

        Node newnode = new Node();
        newnode.Data = data;
        if (position == 1)
        {
            newnode.NextNode = node1;
            node1 = newnode;

        }

    }
}
class Program
{
    static void Main(string[] args)
    {
        Node node = new Node();
        //random Singly LinkedList
        node.CreateLinkedList(10);
        node.CreateLinkedList(11);
        node.CreateLinkedList(12);
        node.CreateLinkedList(13);
        node.CreateLinkedList(14);
        node.CreateLinkedList(15);
        node.InsertNode(20, 1);// this method does not return node value what is inserted.


    }
}

【问题讨论】:

  • 您不能在扩展方法 (yet) 中重新分配 this
  • InsertNode 是无效的,这就是它不返回任何内容的原因
  • 我该怎么办??
  • 你试过调试吗?
  • 为什么要为此创建扩展方法?这些是您对 Node 数据类型的操作。将它们保留为您类型的方法。您的方法的定义也不合适。您的 createlist 实际上只创建一个节点。

标签: c# algorithm linked-list extension-methods


【解决方案1】:

您的代码有很多问题,我们可以稍后处理。但是,让我们先回答您的问题。我会有点直截了当,因为我无法假设你为什么要这样做。

为什么扩展方法在插入操作中不返回修改后的节点。

因为你的方法没有返回任何东西

但在创建链接列表时它工作正常。

是的,因为该代码从未修改过this Node node 参数

扩展方法应该返回修改后的节点。

仅当您实际从该方法返回任何数据时!

什么是做到这一点的完美方法。

见下文

IS扩展方法性能好

扩展方法与什么比较?与类似编写的成员方法相比,与您的示例相关的案例应该没有性能差异

完美的方法:

首先要做的事情是:这里不需要编写扩展方法。你为什么不写一个普通的成员方法?当您要添加功能的类不能直接供您编辑时,通常会进行扩展,通常是因为代码属于第三方

其次,您似乎不太了解引用以及按值传递的工作原理。先贴个更好的代码,再解释一下

public class Node {
    public object Data { get; set; }
    public Node NextNode { get; set; }

    public Node(object data) {
        Data = data;
    }

    public Node AppendNode(object data) {
        var newNode = new Node(data);

        var current = this;
        while (current.NextNode != null)
            current = current.NextNode;
        current.NextNode = newNode;

        return newNode;
    }

    public Node SetFirstNode(object data) {
        return new Node(data) { NextNode = this };
    }
}

class Program {
    static void Main(string[] args) {
        var linkedList = new Node(10);
        linkedList.AppendNode(11);
        linkedList.AppendNode(12);
        linkedList.AppendNode(13);
        linkedList.AppendNode(14);
        linkedList.AppendNode(15);
        linkedList = linkedList.SetFirstNode(20);

    }
}

从您的主要问题(为什么插入不起作用)的角度来看,需要注意的重要事情是方法SetFirstNode 实际上返回了新创建的节点,并且在Main 中,我们重新分配了链表linkedList = linkedList.SetFirstNode(20);

现在,您实际上可以编写一个静态方法并通过 ref 传递链表,但在我看来,这不是一个好习惯。不过,代码如下所示

public static class ListOperations {
    public static void InsertNode(ref Node linkedList, object data) {
        linkedList = new Node(data) { NextNode = linkedList };
    }
}

除其他需要注意的事项外,我故意将node 对象称为linkedListCreateLinkedListAppendNodeInsertNodeSetFirstNode,以便您可以更好地理解代码。

下面是使用通用参数而不是 object Data 并使用正确的 InsertNode 方法的相同代码

public class Node<T> {
    public T Data { get; set; }
    public Node<T> Next { get; set; }

    public override string ToString() {
        return Data.ToString();
    }

    public Node(T data) {
        Data = data;
    }

    public Node<T> AppendNode(T data) {
        var newNode = new Node<T>(data);

        var current = this;
        while (current.Next != null)
            current = current.Next;
        current.Next = newNode;

        return newNode;
    }

    /// <summary>
    /// Inserts a new node into the linkedlist as the desired position
    /// </summary>
    /// <param name="position">0-based index for the final position of new node</param>
    /// <param name="newNode">The newly created node containing data</param>
    /// <returns>returns the first node of the linkedlist</returns>
    public Node<T> InsertNode(T data, int position, out Node<T> newNode) {
        var current = this;
        position--;
        newNode = new Node<T>(data);
        if (position < 0) {
            newNode.Next = current;
            return newNode;
        }

        for (int i = 0; i < position; ++i)
            current = current.Next;
        newNode.Next = current.Next;
        current.Next = newNode;
        return this;
    }
}

class Program {
    static void Main(string[] args) {
        var linkedList = new Node<int>(10);
        linkedList.AppendNode(11);
        linkedList.AppendNode(12);
        linkedList.AppendNode(13);
        linkedList.AppendNode(14);
        linkedList.AppendNode(15);
        linkedList = linkedList.InsertNode(20, 0, out var newNode);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-02
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    • 2010-11-14
    • 2010-09-09
    • 1970-01-01
    相关资源
    最近更新 更多