【问题标题】:Type safety for Dictionary keys?字典键的类型安全?
【发布时间】:2011-01-07 13:56:27
【问题描述】:

我计划在一个项目中使用多个名称索引字典。我的第一选择是使用 string 键,它只是我的 Value 元素的 Name 属性。

然而,这使得字典键相同,即使它们访问不同的类型:

private Dictionary<string, Foo> myFoos;
private Dictionary<string, Bar> myBars;

myFoos[bar.Name];  // shouldn't be able to do this!

我希望这些键彼此类型不兼容,以使它们无法相互混淆:

private Dictionary<FooName, Foo> myFoos;
private Dictionary<BarName, Bar> myBars;

由于为每个Value 类型创建一个*Name 类是多余的,我创建了一个Name&lt;T&gt; 类:

public struct Name<T>
{
    public string Name;

    // for convenience, could be explicit instead
    static implicit operator string(Name<T> name)
    {
        return name.Name;
    }
}

这会给我

private Dictionary<Name<Foo>, Foo> myFoos;
private Dictionary<Name<Bar>, Bar> myBars;

然后我可以存储 Name&lt;Foo&gt; 实例而不是字符串。

这似乎有点笨拙,但这是我迄今为止想出的最好的方法 - 关于如何做得更好的任何建议?
这是误入歧途,还是很棒?

【问题讨论】:

    标签: c# generics dictionary


    【解决方案1】:

    这将起作用,只是您需要覆盖 EqualsGetHashCode 以使名称按值进行比较。

    【讨论】:

      【解决方案2】:

      第一个问题是:

      我希望这些键彼此类型不兼容,以使它们无法相互混淆:

      为什么?真的有混淆的可能吗?这并不明显。请注意,我并不是说您的方法不好。事实上,事实上,这可能有真正的好处。但是考虑数组索引器:

      int a[];
      float b[];
      

      数组的类型不兼容,但都使用整数索引。 是的,当索引混淆时,这实际上会导致问题 - 可能与您在使用密钥时遇到的问题相同。

      所以这个案例和你的完全一样。也许对不同的容器使用相同的密钥类型毕竟不是那么糟糕(即使理论上你是对的,而且存在混淆的风险)。

      【讨论】:

      • 当我想存储 Foo 拥有的 Bars 列表时,问题就出现了。我没有存储 Bars 的第二个副本,而是存储 Bar.Name - 并且 Dictionary> 开始搅浑水。
      • @mskfisher:这是一个糟糕的方法。 不要直接存储条形图,而不仅仅是它们的名称!这不是复制(除非你的 Foos 和 Bars 是结构,在这种情况下它们不应该是结构)。如果它们是类,那么您存储它们将不会复制,它只会存储对对象的引用。这是面向对象的基本属性,您的用例非常普遍,以至于它有一个自己的名称:aggregation
      • @Konrad:很好,还有我应该提到的另一件事。我一直在这个设计的结构和类之间来回走动,因为我想通过值而不是引用在线程之间传递副本。我现在正在研究只使用类并为我需要在线程之间传递的每种类型创建复制构造函数。
      • @mskfisher 听起来你可能只需要一个不可变的引用类型来两全其美?
      • 不幸的是,我需要能够使用 XmlSerializer/Deserializer (反)序列化这些对象,因此它们不能是不可变的。我想我只是要假装它们是不可变的。
      猜你喜欢
      • 2020-12-30
      • 2015-12-10
      • 1970-01-01
      • 1970-01-01
      • 2020-01-03
      • 2018-05-29
      • 1970-01-01
      • 2017-12-15
      • 1970-01-01
      相关资源
      最近更新 更多