c# - 在 C# 中对字典进行切片

标签 c# .net dictionary getter-setter

我正在尝试在 C# 中创建一个类,该类具有从 JSON 文件获取的字典 (bigDict)。 bigDict 将字符串映射到大数据结构。由此,我想创建另一个字典 (smallDict),它将键中的每个字符串映射到 bigDict 的数据结构值中的一个元素(字符串)。

我尝试使用 get 和 set 来创建 smallDict。我能够成功使用 get,但我卡在了 set

class myClass
{
    public Dictionary<string, SomeStruct> bigDict{ get; set; } /*get and set from a JSON file*/

    public virtual Dictionary<string, string> smallDict
    {
        get => bigDict.ToDictionary(x => x.Key, x => x.Value.ElemFromStruct);   //works fine

        set => smallDict.ToDictionary.update(key , value); //doesn't work fine
    }
}

由于无法正确设置,我得到 property or indexer cannot be assigned to, is readonly 在一些预先存在的测试用例中出现错误(我正在重构代码)

最佳答案

定义一个“一次性”类型SmallDict:

    public SmallDict<string> smallDict;

    public myClass()
    {
        smallDict = new SmallDict<string>(bigDict);
    }
    class SmallDict<TKey>
    {
        public readonly Dictionary<TKey, SomeStruct> BigDict;

        public SmallDict(Dictionary<TKey, SomeStruct> bigDict)
        {
            BigDict = bigDict;
        }

        public string this[TKey key]
        {
            get => BigDict[key].ElemFromStruct;
            set {
                var obj = BigDict[key];
                obj.ElemFromStruct = value;
                BigDict[key] = obj;
            }
        }
    }

按如下方式使用:

Console.WriteLine(smallDict["key1"]); // Equivalent to printing bigDict[key].ElemFromStruct
smallDict["key1"] = "new value";      // Equivalent to bigDict[key].ElemFromStruct = "new value"

它只是一个字典的包装器,所以如果您想要比普通索引更多的方法,您将必须手动完成所有管道。

通用性

请注意 SmallDict 如何仅适用于 SomeStruct 的词典...

我本来可以编写一个通用的 DictionarySlice 类,但是任何实际通用性的尝试都会被 C# 严格的类型系统所阻碍:没有令人满意的方式来通用地告诉要切片的属性。

可能的解决方案:

  • getterssetters 作为 lambda 传递——请注意,您当然可以这样做,lambda 中的代码会比实际类中的代码多。如果您需要对许多不同的属性进行切片,它可能会很有用。
  • 使 SomeStruct 实现通用类将使用的 IGetSetElemFromStruct —— 不是非常优雅,如果您有许多属性要切片的话,可能会非常麻烦。
  • 反射(reflection)——为了完整性而包含在内,但不会对其进行扩展...

大型结构

避免大型结构;更重要的是避免可变结构,它被普遍认为是 Very Bad Thing(TM)在 C# 中。 来自 Microsoft's design guidelines ,强调我的:

In general, structs can be very useful but should only be used for small, single, immutable values that will not be boxed frequently.

set {
    var obj = BigDict[key];
    obj.ElemFromStruct = value;
    BigDict[key] = obj;
}

请注意,在上面的 setter 中,我得到了结构的副本,对其进行了修改,然后将其复制回字典中……不太好。如果它很大,帮自己一个忙,使用。然后你会简单地写:

set { BigDict[key].ElemFromStruct = value; }

属性获取/设置中的重要操作

这是关于您作为示例编写的代码:

public virtual Dictionary<string, string> smallDict
{
    get => bigDict.ToDictionary(x => x.Key, x => x.Value.ElemFromStruct);   //works fine

尽可能避免它们。没有明确的行说明属性 getters/setters 中可以包含什么,但是在 get 中创建和填充字典以任何合理的标准来说都太过分了:想象一下如果你不得不怀疑 每个属性访问。

也许根本不用这个

这个解决方案是我能想到的最好的解决方案,但它很笨重而且不是很有用。您必须根据您的用例自行判断,但通常直接访问/修改 bigDict[key].ElemFromStruct 会更好

关于c# - 在 C# 中对字典进行切片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57599159/

相关文章:

c# - Silverlight 3 和动画 gif

c# - 在 C# 中,以下语法的作用是什么 : ((Classname)this. variableName).property

c# - 我可以获得内存映射文件的路径吗? (.NET 4.0)

c++ - 将多个带有 vector 的 map 合并为一张 map

c# - 如何改进 Entity Framework 和 Javascript 交互

C# 使用 VARRAY 参数调用 Oracle 11g 过程

c# - 在 WPF 中进行 DataBound 时将 TextBlock 设置为完全粗体

.net - F#作为脚本语言

python - 合并字典保留旧键和新值

javascript - 在 JavaScript 中使用对象作为字典的时间复杂度