C# 作为泛型的可空类型

C# 作为泛型的可空类型,c#,linked-list,C#,Linked List,我正在尝试为我的个人库创建一个可以处理所有事情的链接列表。我正试图编写它,以便它可以“同样”轻松地手动int,null,DateTime或Class,并且我希望它可以轻松地扩展,这样,如果我想快速地从中生成堆栈,我就可以编写push,pop,和peek方法等等 目前,我的代码如下所示。请注意,我使用“Base”作为泛型类型 namespace ClassLibrary1 { public class LinkedList<Base> where Base : class

我正在尝试为我的个人库创建一个可以处理所有事情的链接列表。我正试图编写它,以便它可以“同样”轻松地手动
int
null
DateTime
Class
,并且我希望它可以轻松地扩展,这样,如果我想快速地从中生成堆栈,我就可以编写
push
pop
,和
peek
方法等等

目前,我的代码如下所示。请注意,我使用“Base”作为泛型类型

namespace ClassLibrary1
{
    public class LinkedList<Base> where Base : class
    {
        public class Node
        {
            private Node next;
            private Node prev;
            private Base value;

            /// <summary>
            /// Constructor for Nodes of Circular Linked List class.
            /// Calls overloaded constructor for no previous or next provided.
            /// O(1)
            /// </summary>
            /// <param name="value">The value to be stored. Can use tuple for associations</param>
            public Node(Base value)
            {
                    new Node(null, null, value);
            }

            /// <summary>
            /// Constructor for nodes of Circular Linked List class.
            /// O(1)
            /// </summary>
            /// <param name="prev">The previous node in the linked list</param>
            /// <param name="next">The next node in the linked list</param>
            /// <param name="value">The value to be stored</param>
            public Node(Node prev, Node next, Base value)
            {
                this.prev = prev;
                this.next = next;
                this.value = value;
            }
            /// <summary>
            /// Sets the  'next' attribute of the node to the passed value.
            /// O(1)
            /// Chainable
            /// </summary>
            /// <param name="next">The new value of the 'next' attribute.</param>
            /// <returns>Chainable(Node, this)</returns>
            public Node setNext(Node next)
            {
                this.next = next;
                return this;
            }

            /// <summary>
            /// Sets the 'prev' attribute of the node to the passed value 
            /// O(1)
            /// Chainable
            /// </summary>
            /// <param name="prev">The new value of the 'prev' attribute to denote the previous node</param>
            /// <returns>Chainable(Node, this)</returns>
            public Node setPrev(Node prev)
            {
                this.prev = prev;
                return this;
            }

            /// <summary>
            /// Changes the stored value of type Base to the passed value.
            /// O(1)
            /// Chainable
            /// </summary>
            /// <param name="value">The new value to be stored with the node</param>
            /// <returns>Chainable(Node, this)</returns>
            public Node setVal(Base value)
            {
                this.value = value;
                return this;
            }

            /// <summary>
            /// Returns the next node in the linked list.
            /// O(1)
            /// </summary>
            /// <returns>The next node in the linked list.(Node)</returns>
            public Node getNext()
            {
                return this.next;
            }

            /// <summary>
            /// Returns the previous node in the linked list.
            /// O(1)
            /// </summary>
            /// <returns>The previous node in the linked list.(Node)</returns>
            public Node getPrev()
            {
                return this.prev;
            }

            /// <summary>
            /// Returns the value stored at this node.
            /// O(1)
            /// </summary>
            /// <returns>The value stored at this node.(Base)</returns>
            public Base getVal()
            {
                return this.value;
            }
        }
        public Node head;
        public bool duplicates;
        public bool hasNullValues;
        public bool throwNullError;

        /// <summary>
        /// Constructor for the LinkedList. Creates a null head node.
        /// Duplication defaulted to false
        /// O(1)
        /// </summary>
        public LinkedList()
        {
            this.head = new Node(null);
            this.head.setNext(this.head).setPrev(this.head);
            this.duplicates = false;
            this.hasNullValues = false;
            this.throwNullError = false;
        }

        /// <summary>
        /// Allows duplication for the linked list.
        /// O(1)
        /// Chainable attribute.
        /// </summary>
        /// <returns>Chainable.(LinkedList<Base>, this)</returns>
        public LinkedList<Base> hasDuplicates()
        {
            this.duplicates = true;
            return this;
        }

        /// <summary>
        /// Allows the structure to store null values in nodes.
        /// O(1)
        /// Chainable.
        /// </summary>
        /// <returns>Chainable.(LinkedList<Base>, this)</returns>
        public LinkedList<Base> hasNulls()
        {
            this.hasNullValues = true;
            return this;
        }

        /// <summary>
        /// Causes the structure to throw a null error when a null value is inserted.
        /// If hasNulls is off, turns it on.
        /// O(1)
        /// Chainable.
        /// </summary>
        /// <returns>Chainable.(LinkedList<Base>, this)</returns>
        public LinkedList<Base> throwsNulls()
        {
            if (!this.hasNullValues)
            {
                this.hasNullValues = true;
            }
            this.throwNullError = true;
            return this;
        }

        /// <summary>
        /// Iff duplicates not allowed, searches for value in list. Throws error if duplicate found.
        /// Creates a new node at the end of the list, then links it to the head node.
        /// O(length) [if hasDuplicates()]
        /// O(1) [if else]
        /// Chainable
        /// </summary>
        /// <param name="value">Value stored at the new node in the list</param>
        /// <returns>Chainable.(LinkedList<Base>, this)</returns>
        public LinkedList<Base> add(Base value)
        {
            if (!duplicates)
            {
                if (search(value) != null)
                {
                    throw new Exception("Value already exists in the linked list.");
                }
            }
            if (!this.hasNullValues && value != null)
            {
                if (this.throwNullError)
                {
                    throw new Exception("Cannot insert null values");
                }
                else
                {
                    return this;
                }
            }
            Node newNode = new Node(value);
            this.head.getPrev().setNext(newNode);
            this.head.setPrev(newNode);
            return this;
        }

        /// <summary>
        /// Iterates through the list until first such node for with a matching value is found.
        /// Returns null if no matches found. 
        /// Use searchAll to find duplicates. 
        /// O(length)
        /// </summary>
        /// <param name="value">The value to be searched for.</param>
        /// <returns>First node with the desired value(Node?)</returns>
        public Node search(Base value)
        {
            Node temp = this.head.getNext();
            while (!temp.getVal().Equals(value))
            {
                if (temp.Equals(this.head))
                {
                    return null;
                }
                temp = temp.getNext();
            }
            return temp;
        }

        /// <summary>
        /// If value doesn't exist in the list, throws an exception.
        /// Deletes the first node found with the chosen value.
        /// Use DeleteAll to delete all instances.
        /// Chainable.
        /// O(length)
        /// </summary>
        /// <param name="value">Value to be removed from the list.</param>
        /// <returns>Chainable.(LinkedList<Base>, this)</returns>
        public LinkedList<Base> delete(Base value)
        {
            try{
                return delete(search(value));
            }
            catch(Exception e){
                throw new Exception("Node to be deleted not found");
            }

        }

        /// <summary>
        /// Removes all pointers to the passed node.
        /// O(1)
        /// </summary>
        /// <param name="tbd">The node to be deleted.</param>
        /// <returns>Chainable.(LinkedList<Base>, this)</returns>
        public LinkedList<Base> delete(Node tbd)
        {
            if (tbd.Equals(this.head))
            {
                throw new Exception("Cannot delete head node");
            }
            else
            {
                tbd.getPrev().setNext(tbd.getNext());
                tbd.getNext().setPrev(tbd.getPrev());
            }
            return this;
        }

        /// <summary>
        /// Returns a LinkedList of all nodes containing the desired value.
        /// O(length)
        /// </summary>
        /// <param name="value">The value to be found.</param>
        /// <returns>A LinkedList of Nodes with matching values.(LinkedList<Node>)</returns>
        public LinkedList<Node> searchAll(Base value)
        {
            LinkedList<Node> returnList = new LinkedList<Node>();
            Node temp = this.head.getNext();
            while (!temp.Equals(this.head))
            {
                if (temp.getVal().Equals(value))
                {
                    returnList.add(temp);
                }
                temp = temp.getNext();
            }
            return returnList;
        }

        /// <summary>
        /// Returns the first Node in the Linked List.
        /// O()
        /// </summary>
        /// <returns>First non-head node in the list.(Node)</returns>
        public Node firstOrDefault()
        {
            return this.head.getNext();
        }

        /// <summary>
        /// Returns the value of the first node in the list.
        /// O(1)
        /// </summary>
        /// <returns>FIrst non-head </returns>
        public Base firstVal()
        {
            return this.head.getNext().getVal();
        }

        /// <summary>
        /// Gets the last node in the linked list.
        /// O(1)
        /// </summary>
        /// <returns>The last node in the linked list.(Node)</returns>
        public Node tail()
        {
            return this.head.getPrev();
        }

        /// <summary>
        /// Returns the value of the last node in the linked list.
        /// O(1)
        /// </summary>
        /// <returns>VThe value of the tail node.(Base)</returns>
        public Base tailVal()
        {
            return this.head.getPrev().getVal();
        }

        public static void Main()
        {
            LinkedLis t<Int32> mine = new LinkedList<Int32>();
        }
    }
}
命名空间类库1
{
公共类链接列表,其中基:类
{
公共类节点
{
私有节点下一步;
私有节点prev;
私人基础价值;
/// 
///循环链表类的节点的构造函数。
///为未提供的上一个或下一个调用重载构造函数。
///O(1)
/// 
///要存储的值。可以使用元组进行关联
公共节点(基值)
{
新节点(null,null,value);
}
/// 
///循环链表类的节点的构造函数。
///O(1)
/// 
///链接列表中的上一个节点
///链接列表中的下一个节点
///要存储的值
公共节点(节点上一个、节点下一个、基值)
{
this.prev=prev;
this.next=next;
这个值=值;
}
/// 
///将节点的“next”属性设置为传递的值。
///O(1)
///可链接
/// 
///“下一个”属性的新值。
///可链接(节点,此)
公共节点设置下一步(节点下一步)
{
this.next=next;
归还这个;
}
/// 
///将节点的“prev”属性设置为传递的值
///O(1)
///可链接
/// 
///“prev”属性的新值表示上一个节点
///可链接(节点,此)
公共节点setPrev(节点prev)
{
this.prev=prev;
归还这个;
}
/// 
///将Base类型的存储值更改为传递的值。
///O(1)
///可链接
/// 
///要与节点一起存储的新值
///可链接(节点,此)
公共节点setVal(基值)
{
这个值=值;
归还这个;
}
/// 
///返回链接列表中的下一个节点。
///O(1)
/// 
///链接列表中的下一个节点。(节点)
公共节点getNext()
{
把这个还给我,下一个;
}
/// 
///返回链接列表中的上一个节点。
///O(1)
/// 
///链接列表中的上一个节点。(节点)
公共节点getPrev()
{
返回此.prev;
}
/// 
///返回存储在此节点上的值。
///O(1)
/// 
///存储在此节点上的值。(基本)
公共基getVal()
{
返回此.value;
}
}
公共节点头;
公共文件副本;
公共价值观;
公共布尔thrownulllerror;
/// 
///LinkedList的构造函数。创建空头节点。
///复制默认为false
///O(1)
/// 
公共链接列表()
{
this.head=新节点(空);
this.head.setNext(this.head).setPrev(this.head);
这个。重复=假;
this.hasNullValues=false;
this.throwNullError=false;
}
/// 
///允许复制链接列表。
///O(1)
///可链接属性。
/// 
///可链接。(链接列表,此)
公共链接列表具有重复项()
{
this.duplicates=true;
归还这个;
}
/// 
///允许结构在节点中存储空值。
///O(1)
///可链接的。
/// 
///可链接。(链接列表,此)
公共链接列表hasNulls()
{
this.hasNullValues=true;
归还这个;
}
/// 
///导致结构在插入空值时抛出空错误。
///如果hasNulls处于禁用状态,则将其打开。
///O(1)
///可链接的。
/// 
///可链接。(链接列表,此)
公共链接列表throwsNulls()
{
如果(!this.hasNullValues)
{
this.hasNullValues=true;
}
this.throwNullError=true;
归还这个;
}
/// 
///Iff不允许重复,搜索列表中的值。如果发现重复,则抛出错误。
///在列表末尾创建一个新节点,然后将其链接到头部节点。
///O(长度)[如果有重复项()]
///O(1)[如另有规定]
///可链接
/// 
///存储在列表中新节点上的值
///可链接。(链接列表,此)
公共链接列表添加(基值)
{
如果(!重复)
{
如果(搜索(值)!=null)
{
抛出新异常(“链接列表中已存在值”);
}
}
如果(!this.hasNullValues&&value!=null)
{
if(this.throwNullError)
{
public class LinkedList<Base> where Base : class
new LinkedList<Int32>()