我正在尝试在 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# 严格的类型系统所阻碍:没有令人满意的方式来通用地告诉要切片的属性。
可能的解决方案:
- 将 getters 和 setters 作为 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/