【问题标题】:How to create the base class of the generic type dictionary to store it in a list?如何创建泛型类型字典的基类以将其存储在列表中?
【发布时间】:2015-01-20 14:08:01
【问题描述】:

我有很多方法可以返回数据集列表,这些数据集表示为键 (DateTime) 和值(一些 ValueTypestring,我不知道)对,以及这些数据套装的尺寸可能约为 10 000 件或更多。例如:

public List<DataSet> GetAnyData(...) 
{
    var resultList = new List<DataSet>(); // Create the list for the base class
    resultList.Add(new DoubleDataSet());  // This classes will be filled in this method
    resultList.Add(new StringDataSet());  // See the description for them below
    return resultList;
}

此方法的结果列表示例:

ListItem1           ListItem2
Date1    Values1    Date2    Values2
01:00     10.5      02:00     "a"
01:15     20.42     02:15     "b"
01:30     30.01     02:30     "c"

收到这些数据集后,我需要通过不同的方式(使用 LINQ)处理它们。而我的问题是:如何创建 DataSet 类?

我尝试了很多解决方案:

1) 使用泛型从 Dictionary 继承 DataSet 类:

abstract class DataSet<T> : Dictionary<DateTime, T> {...}

并创建特定的类:

class DoubleDataSet : DataSet<double> {...}
class StringDataSet : DataSet<string> {...}

但问题是:如何创建可以存储在数据集列表中的基类?

2)创建DataSetDataItem的类,并在第一个解决方案中使用:

class DataItem 
{
    public double DoubleValue { get; set; }
    public string StringValue { get; set; }
    // etc
}

class DataSet : Dictionary<DateTime, DataItem> {...}

但问题是:如何知道我需要取DataItem的什么属性?

3) 将数据存储在object 类中:

public class DataSet : Dictionary<DateTime, object> {...}

public class DoubleDataSet : DataSet
{
    public new double this[DateTime key]
    {
        get { return base[key] as double; }
        set { base[key] = value; }
    }
}

但问题是:装箱和拆箱怎么样?如果我将有 50 000 个值并且每个值都将转换为对象并返回所需的类型,这将花费大量时间。同样使用 LINQ,DataSet 值的类型将是 object,我需要知道它是什么类型。

4) 将带有数据的字典存储在DataSet 类中:

public class DataSet
{
    public Dictionary<DateTime, DataItem> Items {get; set;}
}

public class DoubleDataSet : DataSet
{
    public new Dictionary<DateTime, double> Items
    {
        get { return base.Items  // It wouldn't work because there a new dictionary is created
            .ToDictionary(q => q.Key, q => q.Value.DoubleValue); }
        set { base.Items = value
            .ToDictionary(q => q.Key, q => new DataItem(q.Value, null)); }
    }
}

但问题是:get { return base.Items.ToDictionary(q =&gt; q.Key, q =&gt; q.Value.DoubleValue); } 返回Items 字典的新实例,我无法修改原始列表。

那么请帮助我如何创建泛型类型字典的基类以将其存储在列表中?

如果有任何帮助,我将不胜感激!我知道设计(或编码)存在错误,如果有人能帮助我找到它,我会很高兴!有没有可能解决这个问题?

【问题讨论】:

    标签: c# .net oop generics dictionary


    【解决方案1】:

    如果我理解正确,您需要在列表中存储和处理不同类型的对象,但在处理时,您不知道您正在处理哪种类型的对象。

    您可以尝试一件事:既然您的 DataItem 类知道它是什么类型,为什么不让它决定如何通过实现 visitor 模式来处理它?

    要实现这一点,您必须执行以下操作: 首先,实现不同的数据项:

    // base class you can use in dictionaries
    // note that is does not store any data type
    class DataItem 
    {
        // method called from outside
        // for processing the item
        public abstract void GetProcessed(Processor p);
    }
    
    // DataItem which stores a double
    class DoubleDataItem  : DataItem
    {
        public double Data{get;set;}
    
        public override void GetProcessed(Processor p)
        {
            p.Process(this);
        }
    }
    
    // DataItem which stores a string
    class StringDataItem : DataItem
    {
        public string Data {get;set}
    
        public override void GetProcessed(Processor p)
        {
            p.Process(this);
        }
    }
    

    现在信息,使用哪种类型的数据只存储在相关的类中。每个类还可以检索一个处理器(或访问者)。这个处理器/访问者可以根据它所运行的类型有不同的实现:

    public class Processor
    {
        // do processing for double items
        public void Process(DoubleDataItem d);
        // do processing for string items
        public void Process(StringDataItem d);
    }
    

    现在,当您创建字典时,处理器将根据正在操作的项目执行正确的代码:

    var dictionary = new Dictionary<DateTime,DataItem>();
    // fill dictionary with data item
    var processor = new DoSomethingProcessor();
    foreach (var entry in dictionary)
        entry.Value.GetProcessed(processor);
    

    【讨论】:

    • 非常感谢!这是一个很好的解决方案!我还将对DataSet 类使用此模式来处理其中的所有数据项,例如对可能出现在数据集中的空数据项的值进行插值。
    猜你喜欢
    • 1970-01-01
    • 2010-10-13
    • 1970-01-01
    • 2013-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多