有几个地方我的代码使用方差显着受益,以更好地利用多态性。我真正想做的事情,我知道是不可能的,是这样的:
abstract class A
{
// In my perfect world, this would automatically define a compile-time type:
// a super-type of IReadOnlyDictionary<Q, X>,
// that only includes the members that obey the appropriate variance.
// In the real world, this just doesn't compile.
public abstract IReadOnlyDictionary<in Q, out X> Dict { get; }
}
class B : A
{
// Q:R, and X:Y
public Dictionary<R, Y> SubDict { get; private set; }
public override IReadOnlyDictionary<in Q, out X> Dict { get { return SubDict; } }
}
class C : A
{
// Q:S, and X:Z
public Dictionary<S, Z> SubDict { get; private set; }
public override IReadOnlyDictionary<in Q, out X> Dict { get { return SubDict; } }
}
foreach (A a in alist)
{
Q q = new Q("test key");
X x = a.Dict[key];
Console.WriteLine(x.Information);
}
我怎样才能实现这样的目标?以下是我提出的一些解决方案,但没有一个是理想的。
策略1和2的代码示例:
public interface IReadOnlyDictionaryBase
{
int Count { get; }
}
public interface IReadOnlyDictionaryKeyOut<out TKey> : IReadOnlyDictionaryBase
{
IEnumerable<TKey> Keys { get; }
}
public interface IReadOnlyDictionaryValueOut<out TValue> : IReadOnlyDictionaryBase
{
IEnumerable<TValue> Values { get; }
}
public interface IReadOnlyDictionaryKeyInValueOut<in TKey, out TValue> : IReadOnlyDictionaryValueOut<TValue>
{
TValue this[TKey key] { get; }
bool ContainsKey(TKey key);
TValue GetValueTry(TKey key, out bool success);
}
// A disadvantage of Strategy 1 is that this is not related to the System.Collections.Generic.IReadOnlyDictionary.
// Strategy 2 attempts to reconcile this by adding IReadOnlyDictionary as a base interface here, but that results in ambiguity whenever I try to call one of the members.
public interface IExtendedReadOnlyDictionary<TKey, TValue> : IReadOnlyDictionaryKeyInValueOut<TKey, TValue>, IReadOnlyDictionaryKeyOut<TKey>, IEnumerable<KeyValuePair<TKey, TValue>>
{
bool TryGetValue(TKey key, out TValue value);
}
public class ExtendedDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IExtendedReadOnlyDictionary<TKey, TValue>
{
答案 0 :(得分:0)
听起来你想要使用IReadOnlyDictionary<TKey, TValue>
之类的不变界面和“声明它”作为变体。为了协变,接口必须只能输出泛型类型(如IEnumerable<T>
)。所以你不能简单地采用一个不变的接口,只需通过这种方式声明它就可以变换它。
您的选项#1是可行的,但需要注意。你可以删除不能在新界面中变体的方法,只展示符合你的方差需求的方法,这会让你有类似的东西: / p>
public interface IVariantReadOnlyDictionary<in TKey, out TValue>
{
bool ContainsKey(TKey key);
//bool TryGetValue(TKey key, out TValue value); // cannot be contravariant in TValue
TValue this[TKey key] { get; }
//IEnumerable<TKey> Keys { get; } // cannot be covariant in TKey
IEnumerable<TValue> Values { get; }
int Count { get; }
//cannot extend IEnumerable<KeyValuePair<TKey, TValue>>
}
请注意,IReadOnlyDictionary<TKey, TValue>
的两种方法无法满足您的差异需求,并且您无法以变体方式扩展IEnumerable<KeyValuePair<TKey, TValue>>
。您可以转换为客户端代码中的一种变体方法,但它不是编译时安全的。
请注意,您不能:
IReadOnlyDictionary<TKey, TValue>
转换为IVariantReadOnlyDictionary<TKey, TValue>
。您基本上必须在实现此接口的新类型中“包装”现有字典。