执行此操作之间有何区别:
public static bool IsNullOrEmpty<TKey, TValue>
(this Dictionary<TKey, List<TValue>> dictionary, TKey key)
{
return !dictionary.ContainsKey(key) ||
dictionary.ContainsKey(key) && dictionary[key].Count == 0;
}
这:
public static bool IsNullOrEmpty<TKey, TValue>
(this Dictionary<TKey, TValue> dictionary, TKey key)
where TValue : List<TValue>
{
return !dictionary.ContainsKey(key) ||
dictionary.ContainsKey(key) && dictionary[key].Count == 0;
}
据我所知,编译器没有告诉我没有任何错误。但是,这是否比其他方法更好?它会有任何不同的返回值吗(因为我还没有意识到这一点)?
答案 0 :(得分:3)
首先,您最好尝试来回答这个问题。您很快就会发现,当您尝试以第二种形式调用该函数时,它将无法正常工作。
也就是说,让我们深入研究一下。我们有
public static bool IsNullOrEmpty<TKey, TValue>(
this Dictionary<TKey, List<TValue>> dictionary, TKey key)
与
public static bool IsNullOrEmpty<TKey, TValue>(
this Dictionary<TKey, TValue> dictionary, TKey key)
where TValue : List<TValue>
为什么第二个错误?那么,您想为TValue
传递什么类型的参数?假设我们有一个Dictionary<string, List<int>>
。我们可以使用什么TValue
?它不是int
,因为它不满足约束条件:int
并非源自List<int>
。但这不是List<int>
,因为List<int>>
并非源自List<TValue>
,List<List<int>>
。
所以,现在我们知道第二个错误的原因了。现在让我们回答更多问题:
在什么情况下,这种“递归”约束有意义?
假设我们试图在字典中找到 maximum 键:
public static TKey MaxKey<TKey, TValue>(
this Dictionary<TKey, TValue> dictionary)
where TKey : IComparable<TKey>
{
if (dictionary.Count == 0) throw ...
TKey best = default(TKey);
bool first = true;
foreach(TKey k in dictionary.Keys)
{
if (first || best.CompareTo(k) < 0)
best = k;
first = false;
}
return best;
}
在这里将TKey
约束为IComparable<TKey>
是完全有意义的;我们将比较键。
人们使用和滥用此模式还有哪些其他方式?
有关许多示例,请参见https://blogs.msdn.microsoft.com/ericlippert/2011/02/03/curiouser-and-curiouser/。
为什么第一种方法不够完美?
因为它不能处理以下两种情况:
首先,假设我们有一个多字典,但是它不是从键到列表:
Dictionary<string, int[]>
或
Dictionary<string, Stack<int>>
或
Dictionary<string, IEnumerable<int>>
或其他。
第二,它也不处理案件
class MyList : List<int> {}
...
Dictionary<string, MyList>
尽管这种情况很少见;您不应该正常扩展List<T>
。
实现我的字典方法以实现最大通用性的正确方法是什么?
这是一种方法:
public static bool IsEmpty(this IEnumerable items)
{
// EXERCISE: Why is this implementation bad?
// EXERCISE: Can you improve it?
foreach(var item in items)
return false;
return true;
}
public static bool IsNullOrEmpty<TKey, TValue>(
this Dictionary<TKey, TValue> dictionary, TKey key)
where TValue : IEnumerable
{
return !dictionary.ContainsKey(key) || dictionary[key].IsEmpty();
}
为获得更大的通用性,您可以使用IDictionary
代替Dictionary
。