【问题标题】:Linked List with object-value and datatype具有对象值和数据类型的链表
【发布时间】:2013-03-24 10:06:10
【问题描述】:

实际上,我尝试将链表实现为一个大学项目。 第一步,我编写了一个 ListElementBase 类和严格的 ListElement 类,每个数据类型都从这个类继承。

在第二步中,我尝试编写一个更灵活的单一结构。该结构应保持值作为对象和值的数据类型,以便将值转换为哪种数据类型的信息在对象内。

有点像这样:

private struct Element
{
    public Element Previous;
    public Element Next;

    public object Value;
    public ValueType Type;

    public Element(Element sPrevious, Element sNext, object sValue, ValueType sType)
    {
        Previous = sPrevious;
        Next = sNext;
        Value = sValue;
        Type = sType;
    }
}

但我不明白,如何处理 DataType。我无法为 DataType 创建实例或调用 new Element(..., ..., ..., string) 之类的构造函数。

我是不是完全走错了路?

【问题讨论】:

  • 不,你没有走错路。看来您正朝着正确的方向前进。
  • 您希望您的链接列表能够容纳不同类型的对象,还是每个链接列表仅容纳一种类型的对象?
  • 我想实现一个通用列表,它可以在同一个列表中保存任何数据类型。

标签: c# casting linked-list


【解决方案1】:

好的,您想要创建一个可以包含任何类型(和任何混合)对象的异构列表。 这意味着泛型已经过时了。

object.GetType()

如果你想自动确定传递给Element构造函数的对象的类型,你可以这样做:

public Element(Element sPrevious, Element sNext, object sValue)
{
    Previous = sPrevious;
    Next = sNext;
    Value = sValue;
    Type = (sValue != null) ? sValue.GetType() : typeof(object);
}

换句话说,您可以完全避免传递类型参数,而只需向对象询问。

这是因为所有对象都派生自System.Object,并且存在一个方法System.Object.GetType()

但是,如果sValue 为空,它不会工作,这就是为什么我检查空并将类型设置为object 如果sValue 为空。

如果你想传入空对象并保持指定类型的能力(这会有点奇怪,但仍然......)那么你可以有另一种根本不指定对象的方法,只是一个类型:

public Element(Element sPrevious, Element sNext, Type type)
{
    Previous = sPrevious;
    Next = sNext;
    Value = null;
    Type = type;
}

不过,我质疑它的实用性。

typeof()

您缺少的另一条信息是,您可以使用 typeof() 运算符从类型名称中获取 Type 对象,例如:

Type t1 = typeof(string);
Type t2 = typeof(int);

我不确定您将如何实际使用值和类型;我想你将不得不有很多“检查类型和转换”代码,我不确定这是一个好主意......

【讨论】:

    【解决方案2】:

    尝试使用泛型而不是手动转换和类型存储。

    (当然,List 和 LinkedList 已经在 .Net 框架中实现了)

    【讨论】:

    • 我知道列表已经在 .Net 中实现。如前所述,我目前正在研究信息学,并尝试自己实现一个链表,只是为了学习的效果,不管它是否有用。
    【解决方案3】:

    使用泛型对双链表中的元素最简单、最天真的实现如下:

    public class Element<T>
    {
        public Element<T> Prev { get; set; }
        public Element<T> Next { get; set; }
        public T Value { get; set; }
    
        public Element(T value, Element<T> prev, Element<T> next)
        {
            Prev = prev;
            Next = next;
            Value = value;
        }
    }
    

    T 是一个类型参数,你可以指定任何你想要的。现在您可以省略ValueType,因为现在您可以在类实现之外获得element.Value.GetType() 和类实现内部typeof(T) 之类的值类型。

    要创建一个列表,请使用下一个代码 sn -p:

    var now = DateTime.Now;
    var first  = new Element<DateTime>(now, null, null);
    
    var second = new Element<DateTime>(now.AddDays(1), first, null);
    first.Next = second;
    
    var third = new Element<DateTime>(now.AddDays(2), second, null);
    second.Next = third;
    

    考虑使用方法创建一些工厂,这将创建您的对象。然后您可以省略指定泛型参数,它们将从方法的使用中推导出(或推断)。例如:

    public class Factory
    {
       public static Element<T> Create<T>(T value, Element<T> prev, Element<T> next)
       {
            return new Element<T> (value, prev, next);
       }
    }
    

    现在您可以创建如下元素:

    var now = DateTime.Now;
    
    var first  = Factory.Create(now, null, null);
    
    var second = Factory.Create(now.AddDays(1), first, null);
    first.Next = second;
    
    var third = Factory.Create(now.AddDays(2), second, null);
    second.Next = third;
    

    当您有许多不同的泛型参数时,这会派上用场。

    【讨论】:

    • .NET LinkedList&lt;T&gt; 是双向链接的。
    • 好吧,你只是展示了一个单链表的实现,而 OP 的问题表明他/她想要一个双链表。
    • @antonijn ou,好的。我注意到了关于双链表的一句话。但是好的,我会更新我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-12
    相关资源
    最近更新 更多