gpt4 book ai didi

C# IDictionary.Keys 和 IDictionary.Values : what is the most optimal implementation?

转载 作者:行者123 更新时间:2023-11-30 22:20:52 28 4
gpt4 key购买 nike

我有一个用作字典的 C# 类,所以我现在正在支持 IDictionary。

除了属性 Keys 和 Values 之外一切都很好:

ICollection<TKey> Keys { get; }
ICollection<TValue> Values { get; }

我内部没有键或值的集合,所以我想知道如何将它们作为 ICollection 提供。

我的第一次尝试是像这样使用“ yield 返回”的魔力:

ICollection<TValue> Values { 
get {
for( int i = 0; i < nbValues; ++i ) {
yield return GetValue(i);
}
}
}

但是当然这不起作用,因为返回的类型不是 IEnumerator 而是 ICollection...

这太糟糕了,因为这本来是最简单的解决方案!

我的第二次尝试是将我的值复制到新创建的数组中并返回该数组。

ICollection<TValue> Values { 
get {
TValue[] copy = new TValue[nbValues];
for( int i = 0; i < nbValues; ++i ) {
copy[i] = GetValue(i);
}
return copy;
}
}

这可行,因为 Array 支持 ICollection。
但问题是 ICollection 有添加和删除条目的方法。如果调用者调用这些方法,只会修改副本而不是字典...

我选择的最终解决方案是让我的字典支持 IDictionary,但也支持 ICollection 和 ICollection,这样我就可以从属性 Keys 和 Values 返回这些集合...

public class MyDictionary : IDictionary<TKey,TValue>, 
ICollection<TKey>,
ICollection<TValue>
{
}

所以现在属性键和值的获取访问器只返回“this”,即:字典。

ICollection<TValue> Values { 
get {
return this;
}
}

这可能是最佳解决方案,但我发现每当您想实现 IDictionary 时都必须实现两个额外的接口(interface),这很麻烦。

你还有别的想法吗?

我在想也许将副本作为数组返回并不是一个坏主意。无论如何,IDictionary 中已经有一个 Add 和 Remove 方法,使用起来更有意义。

也许返回一个包装数组的 ReadOnlyCollection 会更好,因为任何修改返回集合的尝试都会失败?

ICollection<TValue> Values { 
get {
TValue[] copy = new TValue[nbValues];
for( int i = 0; i < nbValues; ++i ) {
copy[i] = GetValue(i);
}
return new System.Collections.ObjectModel.ReadOnlyCollection<TValue>(copy);
}
}

最佳答案

我个人不希望您能够通过 Keys 从字典中删除键和值和 Values无论如何 - 我认为这样做很好。

返回 ReadOnlyCollection<T>很好 - 如果调用者尝试修改集合,那么调用者只会得到一个异常,而不是只是被默默地忽略。

该异常遵循 Dictionary<TKey, TValue> 的行为顺便说一句:

using System;
using System.Collections.Generic;

class Test
{
static void Main()
{
IDictionary<string, string> dictionary =
new Dictionary<string, string> {{ "a", "b" }};
dictionary.Keys.Clear();
Console.WriteLine(dictionary.Count);
}
}

结果:

Unhandled Exception: System.NotSupportedException: Mutating a key collection
derived from a dictionary is not allowed.
at System.Collections.Generic.Dictionary`2
.KeyCollection.System.Collections.Generic.ICollection<TKey>.Clear()
at Test.Main()

正如 SLaks 所说,如果您可以创建自己的 ICollection<T> 实现这是懒惰的,那会更好 - 但如果由于某种原因这很棘手,或者实际上如果性能对你来说并不重要,只需创建数组并将其包装在 ReadOnlyCollection<T> 中很好。不过,您应该考虑以任何一种方式记录预期的性能。

如果您确实创建了自己的惰性实现,需要注意一件事:您可能应该有某种“版本号”,以确保在基础数据发生更改时使返回的集合无效。

关于C# IDictionary.Keys 和 IDictionary.Values : what is the most optimal implementation?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14755903/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com