【问题标题】:How to convert a dictionary to my class implementing a dictionary of the same type?如何将字典转换为实现相同类型字典的类?
【发布时间】:2016-12-07 03:46:29
【问题描述】:

如果我有

public class Stats : Dictionary<string, double>
{
}

public class Info : Dictionary<string, Stats>
{
}

var data = new Dictionary<string, Dictionary<string, double>> {
    { "1", new Dictionary<string, double> {  { "a", 11 } } },
    { "2", new Dictionary<string, double> {  { "aa", 111 } } },
};

为什么我做不到:

var test = (Info)data;

以及我需要使用什么运算符或代码才能实例化我的

[class inheriting from a Dictionary&lt;string, Dictionary&lt;string, double&gt;&gt;]

从一个

Dictionary&lt;string, Dictionary&lt;string, double&gt;&gt;?

【问题讨论】:

  • 您不能从基类实例化,然后将其用作继承类的对象。你想用它做什么?
  • @AshkanSirous:这个课程只是为了清理代码并在任何地方使用我的类名而不是Dictionary&lt;string, Dictionary&lt;string, double&gt;&gt;
  • 我猜你对那个对象有一些功能。正确的?创建一个类并将该对象作为该类的属性并用功能封装它。顺便说一句,这对我来说似乎是一个错误的设计。你想用 1 个键有 2 个值吗?为什么你有一本字典的字典?
  • 这里你可以找到从字典继承的方法:stackoverflow.com/questions/1594997/…
  • 如果你有一本字典,它会以同样的方式工作,但我确定你的设计有误

标签: c# generics type-conversion


【解决方案1】:

您的方法确实存在两个不同的错误:

  1. Dictionary&lt;string, Stats&gt;Dictionary&lt;string, Dictionary&lt;string, double&gt;&gt; 不同。将Info 视为继承Dictionary&lt;string, Dictionary&lt;string, double&gt;&gt; 是错误的。它继承了Dictionary&lt;string, Stats&gt;,完全不同。
  2. 即使您获得了正确的基类型,也不能只是将基类型的任何随机实例强制转换为派生类型。请参阅Convert/Cast base type to Derived type,了解讨论此问题的众多现有 Stack Overflow 问答主题之一。

如果没有一个好的Minimal, Complete, and Verifiable code example,就不可能确定你的代码是如何工作的,或者需要什么才能让它做你想做的事情。但是在您的特定示例中,您可能能够声明一个显式转换,当您使用强制转换运算符时将调用该转换。

例如:

public class Info : Dictionary<string, Stats>
{
    public static explicit operator Info(Dictionary<string, Dictionary<string, double>> source)
    {
        Info result = new Info();

        foreach (var kvp in source)
        {
            result.Add(kvp.Key, Stats.FromDictionary(kvp.Value));
        }

        return result;
    }
}

地点:

public class Stats : Dictionary<string, double>
{
    public static Stats FromDictionary(Dictionary<string, double> source)
    {
        Stats result = new Stats();

        foreach (var kvp in source)
        {
            result.Add(kvp.Key, kvp.Value);
        }

        return result;
    }
}

理想情况下,我们希望能够在Info 中做类似的事情:

public class Stats : Dictionary<string, double>
{
    public static explicit operator Stats(Dictionary<string, double> source)
    {
        Stats result = new Stats();

        foreach (var kvp in source)
        {
            result.Add(kvp.Key, kvp.Value);
        }

        return result;
    }
}

但这是编译器错误:

Stats.explicit operator Stats(System.Collections.Generic.Dictionary)':不允许用户定义的与基类之间的转换

这里更彻底地解决了这个问题:User-defined conversion operator from base class。简短的版本是,如果编译器允许这样做,那么如果您尝试从基引用转换为派生引用,那么其意图将是模棱两可的。在这种情况下,语言会强制您明确表达。

那么您要使用的语句将起作用:

var test = (Info)data;

说了这么多,在你写的cmets中:

该类只是为了清理代码并在任何地方使用我的类名而不是Dictionary&lt;string, Dictionary&lt;string, double&gt;&gt;

如果是这种情况,那么您可能只想使用类型名称别名而不是继承。例如:

using Stats = System.Collections.Generic.Dictionary<string, double>;
using Info = System.Collections.Generic
    .Dictionary<string, System.Collections.Generic.Dictionary<string, double>>;

然后您可以将名称 StatsInfo 分别与 Dictionary&lt;string, double&gt;Dictionary&lt;string, Dictionary&lt;string, double&gt;&gt; 互换使用。

【讨论】:

  • 我学到了一个很好的代码。谢谢。 :) 顺便说一句,我从来没有遇到过这种情况。为什么有人需要一本字典。我觉得有点奇怪
  • 我在声明 Stats 的显式运算符时收到错误 Stats.explicit operator Stats(System.Collections.Generic.Dictionary&lt;string,double&gt;)': user-defined conversions to or from a base class are not allowed...你知道为什么吗?
  • @Ibiza:哦,哎呀。我忘记了。一个很好的解释在这里:User-defined conversion operator from base class。我会更新答案来解决这个问题。
猜你喜欢
  • 2018-08-17
  • 2012-03-01
  • 2021-07-25
  • 2021-09-16
  • 2010-10-16
  • 1970-01-01
  • 1970-01-01
  • 2021-08-29
相关资源
最近更新 更多