C#:如何使用包含接口值的IReadOnly字典(来自包含具体值的具体字典)实现接口

C#:如何使用包含接口值的IReadOnly字典(来自包含具体值的具体字典)实现接口,c#,C#,在我的代码中,我声明了内部类和公共接口,我有一种情况,我想用一个包含接口类型值的IReadonlyDictionary公开一个接口,但我想用一个具有具体类型值字典的类来实现它 我之所以需要它,是因为我正在将一些JSON反序列化为具体类型,并且我希望将反序列化的数据公开为只读 我已经实现了它,如下所示,通过懒洋洋地创建一个新的字典,其中具体的值被转换到接口值中。有没有一种方法可以做到这一点,而不必创建新的词典 //在这段代码中,我想公开一个IReadonlyDictionary。 //通过使用带有

在我的代码中,我声明了内部类和公共接口,我有一种情况,我想用一个包含接口类型值的IReadonlyDictionary公开一个接口,但我想用一个具有具体类型值字典的类来实现它

我之所以需要它,是因为我正在将一些JSON反序列化为具体类型,并且我希望将反序列化的数据公开为只读

我已经实现了它,如下所示,通过懒洋洋地创建一个新的字典,其中具体的值被转换到接口值中。有没有一种方法可以做到这一点,而不必创建新的词典

//在这段代码中,我想公开一个IReadonlyDictionary。
//通过使用带有字典的具体类型从JSON反序列化数据
//使用SomeValue类型的值,该值必须具有要反序列化的公共getter/setter。
//我想这样做,而不是复制和铸造到一个新的字典,如图所示。
//可能吗?
公共接口值{}
内部类SomeValue:ISomeValue{}
公共接口I配置{
IREADONLYDICTIONAL值{get;}
}
内部类配置:IConfiguration{
公共配置(){
_值=新的延迟()
=>Values.ToDictionary(x=>x.Key,x=>(isomValue)x.Value));
}
公共字典值{get;}=null!;
私人懒惰价值观;
IReadOnlyDictionary IConfiguration.Values=>\u Values.Value;
}
我想这样做,而不是复制和铸造到一个新的字典,如图所示

您不能在显式接口实现中直接返回
,因为的两个泛型参数都是泛型的。如果只有
TValue
是协变的,您就可以直接这样做:

public Dictionary<string, SomeValue> Values { get; } = new Dictionary<string, SomeValue>();
IReadOnlyDictionary<string, ISomeValue> IConfiguration.Values => Values;
公共字典值{get;}=new Dictionary();
iRadonlyDictionary IConfiguration.Values=>Values;
但是使用
TValue
作为参数,
IReadOnlyDictionary
强制在
TValue
上保持不变

我建议您在其他方面使代码看起来更漂亮。例如,您可以将创建新词典的很长一行代码提取到扩展方法中

我想这样做,而不是复制和铸造到一个新的字典,如图所示

您不能在显式接口实现中直接返回
,因为的两个泛型参数都是泛型的。如果只有
TValue
是协变的,您就可以直接这样做:

public Dictionary<string, SomeValue> Values { get; } = new Dictionary<string, SomeValue>();
IReadOnlyDictionary<string, ISomeValue> IConfiguration.Values => Values;
公共字典值{get;}=new Dictionary();
iRadonlyDictionary IConfiguration.Values=>Values;
但是使用
TValue
作为参数,
IReadOnlyDictionary
强制在
TValue
上保持不变


我建议您在其他方面使代码看起来更漂亮。例如,您可以将创建新词典的很长一行代码提取到扩展方法中。

您必须创建新对象,但不必创建原始词典的副本。相反,可以使用新形状在原始词典上创建视图。下面是一些完全未经测试但简单的代码,我认为应该可以工作:

public类readonlydictionary rapper:IReadOnlyDictionary
其中TOriginalValue:TValue
{
私人只读IREADONLYDICTIONAL原件;
公共只读词典(IReadOnlyDictionary原件)=>
this.original=原件;
公共TValue此[TKey]=>原始[key];
public IEnumerable Keys=>original.Keys;
public IEnumerable Values=>original.Values.Cast();
public int Count=>original.Count;
public bool ContainsKey(TKey)=>original.ContainsKey(key);
公共IEnumerator GetEnumerator()=>
选择(pair=>newkeyvaluepair(pair.Key,pair.Value))
.GetEnumerator();
公共bool TryGetValue(TKey键,out TValue值)
{
bool ret=原始.TryGetValue(键,out var originalValue);
值=原始值;
返回ret;
}
IEnumerator IEnumerable.GetEnumerator()=>GetEnumerator();
}

我建议在
配置
构造函数中创建一个这样的实例,要包装
\u值
,您必须创建一个新对象,但不必创建原始词典的副本。相反,可以使用新形状在原始词典上创建视图。下面是一些完全未经测试但简单的代码,我认为应该可以工作:

public类readonlydictionary rapper:IReadOnlyDictionary
其中TOriginalValue:TValue
{
私人只读IREADONLYDICTIONAL原件;
公共只读词典(IReadOnlyDictionary原件)=>
this.original=原件;
公共TValue此[TKey]=>原始[key];
public IEnumerable Keys=>original.Keys;
public IEnumerable Values=>original.Values.Cast();
public int Count=>original.Count;
public bool ContainsKey(TKey)=>original.ContainsKey(key);
公共IEnumerator GetEnumerator()=>
选择(pair=>newkeyvaluepair(pair.Key,pair.Value))
.GetEnumerator();
公共bool TryGetValue(TKey键,out TValue值)
{
bool ret=原始.TryGetValue(键,out var originalValue);
值=原始值;
返回ret;
}
IEnumerator IEnumerable.GetEnumerator()=>GetEnumerator();
}
我建议在
配置
构造函数中创建一个实例,以包装
\u值

无需实际复制字典。cre是完全可行的