我有以下方法:
private string TickIfHeadingPresent<TKey, TValue>(Dictionary<TKey, ISet<TValue>> data, TKey key, TValue value)
{
ISet<TValue> set;
return data.TryGetValue(key, out set) && set.Contains(value) ? "<i class='icon-check'></i>" : String.Empty;
}
有时我用我刚创建的对象调用方法,C# 知道我特别有一个 Dictionary<whatever, HashSet<something>>.
在那些情况下我得到错误:
cannot convert from 'System.Collections.Generic.Dictionary<string, System.Collections.Generic.HashSet<string>>' to 'System.Collections.Generic.Dictionary<string, System.Collections.Generic.ISet<string>>'
这让我很困惑,因为 HashSet<T>
是 ISet<T>
的子集- 当然任何接受 ISet<T>
的代码不介意获得特定类型的套装吗?
根据 Visual Studio 的“修复”是添加具有更具体重载的重复方法:
// I have no idea why this won't just hit the ISet overload...
private string TickIfHeadingPresent<TKey, TValue>(Dictionary<TKey, HashSet<TValue>> data, TKey key, TValue value)
{
HashSet<TValue> set;
return data.TryGetValue(key, out set) && set.Contains(value) ? "<i class='icon-check'></i>" : String.Empty;
}
有什么方法可以让我只定义一次方法吗?
最佳答案
假设您有 Dictionary<string, HashSet<string>>
正如你所描述的。假设您以某种方式能够将其作为 Dictionary<string, ISet<string>>
传递.如果是这种情况,您现在可以添加其他实现 ISet<string>
的对象。这本词典,不仅HashSet<string>
.例如,您现在可以添加 SortedSet<string>
到你的字典。但是SortedSet
不是 HashSet
, 也不是来自 HashSet<string>
, 和你原来的 Dictionary
只能包含 HashSet
秒。该示例显示了为什么不允许从 Dictionary<string, HashSet<string>>
转换至 Dictionary<string, ISet<string>>
.
现在,对于某些接口(interface),您不能执行此类违反类型安全的操作。例如 IEnumerable<T>
.如果你有这样的方法:
private string TickIfHeadingPresent<TKey, TValue>(IEnumerable<ISet<TKey>> data, TKey key, TValue value)
现在您可以通过 List<HashSet<string>>
作为IEnumerable<ISet<string>>
.您不能将新项目添加到 IEnumerable<T>
,你也不能做任何其他违反类型安全的操作。这是有保证的,因为 IEnumerable 是这样定义的:
public interface IEnumerable<out T> : IEnumerable
“out”关键字意味着 T 是协变的,编译器将确保此接口(interface)上的任何方法都不会违反这一点(基本上它不允许使用类型 T 作为任何方法的参数,只能作为返回类型)。
关于c# - 为什么我的代码需要重载 HashSet<T> 而不是 ISet<T>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40781052/