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();
}
}