猿问

在 C# 中对字典进行切片

bigDict我正在尝试在 C# 中创建一个类,该类具有从 JSON 文件获取的字典 ( )。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在一些预先存在的测试用例中遇到错误(我正在重构代码)


萧十郎
浏览 121回答 2
2回答

慕的地8271018

定义“一次性”类型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].ElemFromStructsmallDict["key1"] = "new value";      // Equivalent to bigDict[key].ElemFromStruct = "new value"它只是字典的包装,因此如果您想要比普通索引更多的方法,则必须手动完成所有管道操作。通用性请注意如何SmallDict仅适用于SomeStruct...的词典我本想编写一个通用的DictionarySlice类,但任何实际通用性的尝试都会受到 C# 严格类型系统的阻碍:没有令人满意的方法来通用地告诉要对哪个属性进行切片。可能的解决方案:将getter和setter作为 lambda 传递——当然您可以这样做,请注意,您的 lambda 中的代码将比实际类中的代码多。如果您需要对许多不同的属性进行切片,它可能会很有用。制作泛型类将使用的SomeStruct实现——不是非常优雅,而且如果您有许多属性需要切片,则可能非常麻烦。IGetSetElemFromStruct反射——包含在内是为了完整性,但不会对其进行扩展......大型结构避免大型结构;更重要的是,避免可变结构,这在 C# 中被普遍认为是非常糟糕的事情(TM) 。根据微软的设计指南,我的重点是:一般来说,结构体非常有用,但只能用于不会经常装箱的小型、单一、不可变的值。set {    var obj = BigDict[key];     obj.ElemFromStruct = value;     BigDict[key] = obj; }请注意,在上面的 setter 中,我获取了结构的副本,修改它,然后将其复制回字典......不太好。如果它很大,请帮自己一个忙并使用class. 然后你可以简单地写: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以任何合理的标准来看,在 a 中创建和填充字典都太过分了:想象一下,如果您不得不怀疑每个属性访问。也许根本不使用这个这个解决方案是我能想到的最好的解决方案,但它很笨重而且不是很有用。您必须根据您的用例自行判断,但通常直接访问/修改bigDict[key].ElemFromStruct会更好。

拉风的咖菲猫

如果我理解正确的话,您希望能够Dictionary<string, SomeStruct>从Dictionary<string, string>. 为此,您需要从字符串 Value 创建该结构的实例。这是可以完成的,但这意味着该SomeStruct值ElemFromStruct在set.请注意,对于任何属性,在set方法内部,都有一个value与属性(在本例中)类型相同的可用变量Dictionary<string, string>,它表示传递到方法中的项set。这在下面用作value.ToDictionary(...例如:public virtual Dictionary<string, string> SmallDict{&nbsp; &nbsp; get&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return BigDict.ToDictionary(x => x.Key, x => x.Value.ElemFromStruct);&nbsp; &nbsp; }&nbsp; &nbsp; set&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; BigDict = value.ToDictionary(x => x.Key,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x => new SomeStruct {ElemFromStruct = x.Value});&nbsp; &nbsp; }}但是,如果目的只是提供一种SmallDict从 a获取 a 的方法BigDict(而不是相反),那么您可以删除该set方法,因为允许用户BigDict仅基于a 进行设置可能没有多大意义每个值对应一个字符串SomeStruct:public virtual Dictionary<string, string> SmallDict{&nbsp; &nbsp; get&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return BigDict.ToDictionary(x => x.Key, x => x.Value.ElemFromStruct);&nbsp; &nbsp; }}
随时随地看视频慕课网APP
我要回答