C# 自定义集合返回第一个空元素

C# 自定义集合返回第一个空元素,c#,generics,collections,C#,Generics,Collections,我正在尝试重新创建通用列表集合。这是我将项目添加到集合并显示所有项目的代码: public class Collect<TItem> { public Collect<TItem> collectObject; public TItem firstObject; public void Add(TItem item) { if (collectObject == null) { co

我正在尝试重新创建通用列表集合。这是我将项目添加到集合并显示所有项目的代码:

public class Collect<TItem>
{
    public Collect<TItem> collectObject;
    public TItem firstObject;

    public void Add(TItem item)
    {
        if (collectObject == null)
        {
            collectObject = new Collect<TItem>();
            collectObject.firstObject = item;
        }
        else 
        {
            this.collectObject.Add(item);
        }
    }

    public void Show()
    {
        if (firstObject != null)
            Console.WriteLine(firstObject.ToString());

        if (collectObject != null)
            collectObject.Show();           
    }
这是因为第一个
firstObject
变量从未赋值并获得默认值,但我无法找到一种方法来修复它。我学习的这本书在一个构造函数中分配了第一个
firstObject
变量,该构造函数需要一个
TItem
对象,但我不想为这个集合使用构造函数(重新创建列表)


我知道这与一般列表的工作原理完全相同,但我只想了解它背后的逻辑。谢谢你的帮助。

你做错的是
collectObject.firstObject=item应该是
this.firstObject=项

您做错的是
collectObject.firstObject=item应该是
this.firstObject=项

好的,这是在做我的头,但我想你想做一些类似的事情:

if (collectObject == null)
    {
        collectObject = new Collect<TItem>();
        this.firstObject = item;
    }
if(collectObject==null)
{
collectObject=newcollect();
this.firstObject=项目;
}

因为否则,您永远不会为正在创建的对象的firstobject属性指定任何内容。

好的,这是在做我的头,但我认为您希望执行以下操作:

if (collectObject == null)
    {
        collectObject = new Collect<TItem>();
        this.firstObject = item;
    }
if(collectObject==null)
{
collectObject=newcollect();
this.firstObject=项目;
}

因为否则,您永远不会实际将任何内容指定给正在创建的对象的firstobject属性。

我认为您只需更改行: collectObject.firstObject=项目; 到 第一个对象=项目

这样,您的定制收藏将始终由“头”和“尾”表示-我想这就是您想要完成的


换句话说,在添加项目时,您会说“如果这是第一次添加,那么这是我的列表“头”,否则-将其插入列表的“尾”。打印也有同样的想法-打印“头部”,然后调用尾部的打印方法(在代码“Show”方法中)。

我认为您只需更改行: collectObject.firstObject=项目; 到 第一个对象=项目

这样,您的定制收藏将始终由“头”和“尾”表示-我想这就是您想要完成的


换句话说,在添加项目时,您会说“如果这是第一次添加,那么这是我的列表“头”,否则-将其插入列表的“尾”。打印与此相同-打印“头部”,然后调用尾部的打印方法(在代码“Show”方法中)。

首先,这肯定不是
System.Collections.Generic.List
的工作方式。它在内部使用数组,而不是像您这样使用单个链接列表
LinkedList
与您的收藏有些相似,只是它使用了一个双重相似的列表

现在,谈谈你的问题。集合的问题在于它不能表示空值,而您似乎希望这样。我建议创建另一个表示整个集合的公共类,并将您的
集合
仅更改为内部实现(我们称之为
节点
)。这样,新集合类在第一次构造时可以包含对
节点的
null
引用,这表示一个空集合

如果这是生产代码,我很确定您实际上需要这样做,因为您需要在每个集合的基础上保留一些信息(比如count)

另一个选项(通常由函数式语言中的列表采用)是创建类似以下内容的继承层次结构:

abstract class Node<T>
{ }

class FullNode<T> : Node<T>
{
    public T Item { get; private set; }
    public Node<T> Next { get; private set }

    // constructor and possibly other members
}

class EmptyNode<T> : Node<T>
{ }
抽象类节点
{ }
类FullNode:Node
{
公共T项{get;私有集;}
公共节点下一个{get;private set}
//构造函数和可能的其他成员
}
类EmptyNode:Node
{ }
这样,您就可以使用不同的类型来表示完整节点和空节点。在这些列表中,通常会在前面添加新项目,而不是在后面

关于添加的速度,我建议至少还有一个改进,但我想你的书会达到这个目的


另外,我很确定情况确实如此,但我真的希望您不打算在任何类型的生产环境中使用此代码,这只是一个学习练习。

首先,这肯定不是
System.Collections.Generic.List
的工作方式。它在内部使用数组,而不是像您这样使用单个链接列表
LinkedList
与您的收藏有些相似,只是它使用了一个双重相似的列表

现在,谈谈你的问题。集合的问题在于它不能表示空值,而您似乎希望这样。我建议创建另一个表示整个集合的公共类,并将您的
集合
仅更改为内部实现(我们称之为
节点
)。这样,新集合类在第一次构造时可以包含对
节点的
null
引用,这表示一个空集合

如果这是生产代码,我很确定您实际上需要这样做,因为您需要在每个集合的基础上保留一些信息(比如count)

另一个选项(通常由函数式语言中的列表采用)是创建类似以下内容的继承层次结构:

abstract class Node<T>
{ }

class FullNode<T> : Node<T>
{
    public T Item { get; private set; }
    public Node<T> Next { get; private set }

    // constructor and possibly other members
}

class EmptyNode<T> : Node<T>
{ }
抽象类节点
{ }
类FullNode:Node
{
公共T项{get;私有集;}
公共节点下一个{get;private set}
//构造函数和可能的其他成员
}
类EmptyNode:Node
{ }
这样,您就可以使用不同的类型来表示完整节点和空节点。在这些列表中,通常会在前面添加新项目,而不是在后面

我会建议
if (firstObject != default(TItem))
Collect<int?> test = new Collect<int?>();
public class Collect<TItem> where TItem : struct
{
    public Collect<TItem> collectObject;
    public TItem? firstObject;

    public void Add(TItem item)
{
        if (collectObject == null)
        {
            collectObject = new Collect<TItem>();
            firstObject = item;
        }
        else 
        {
            this.collectObject.Add(item);
        }
    }

    public void Show()
    {
        if (firstObject.HasValue)
            Console.WriteLine(firstObject.ToString());

        if (collectObject != null)
            collectObject.Show();           
    }
}