C# 声明显式泛型参数和使用约束之间有什么区别?

C# 声明显式泛型参数和使用约束之间有什么区别?,c#,generics,constraints,C#,Generics,Constraints,这样做的区别是什么: public static bool IsNullOrEmpty<TKey, TValue> (this Dictionary<TKey, List<TValue>> dictionary, TKey key) { return !dictionary.ContainsKey(key) || dictionary.ContainsKey(key) &&

这样做的区别是什么:

    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;
    }
公共静态bool为空
(这本字典,TKey)
{
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;
    }
公共静态bool为空
(这本字典,TKey)
其中TValue:List
{
return!dictionary.ContainsKey(key)|
dictionary.ContainsKey(key)&&dictionary[key].Count==0;
}

据我所知,编译器没有告诉我没有任何错误。但是,这种方法比另一种更好吗?它会有不同的返回值吗(因为我还没有意识到这一点)?

首先:你自己回答这个问题的最佳选择是尝试一下。您很快就会发现,当您试图以第二种形式调用函数时,它不起作用

也就是说,让我们深入研究一下。我们有

public static bool IsNullOrEmpty<TKey, TValue>(
  this Dictionary<TKey, List<TValue>> dictionary, TKey key)
在这里,将
TKey
约束为
IComparable
是完全有意义的;我们要比较一下钥匙

人们使用和误用这种模式的其他方式有哪些

有关许多示例,请参见

为什么第一种方法不够完美

因为它不处理这两种情况:

首先,假设我们有一个多字典,但它不是从键到列表:

Dictionary<string, int[]>
字典

字典

字典
或者别的什么

第二,它也不处理这个案件

class MyList : List<int> {}
...
Dictionary<string, MyList>
class MyList:List{}
...
字典
尽管这种情况非常罕见;您不应该正常扩展
列表

为了实现最大的通用性,实现字典方法的正确方法是什么

这里有一个方法:

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();
}
公共静态bool为空(此IEnumerable items)
{
//练习:为什么这个实现不好?
//练习:你能改进它吗?
foreach(项目中的var项目)
返回false;
返回true;
}
公共静态bool为空(
这本字典(TKey)
其中TValue:IEnumerable
{
return!dictionary.ContainsKey(key)| | dictionary[key].IsEmpty();
}

为了更具概括性,您可以先使用
IDictionary
而不是
Dictionary

:您自己回答这个问题的最佳选择是尝试一下。您很快就会发现,当您试图以第二种形式调用函数时,它不起作用

也就是说,让我们深入研究一下。我们有

public static bool IsNullOrEmpty<TKey, TValue>(
  this Dictionary<TKey, List<TValue>> dictionary, TKey key)
在这里,将
TKey
约束为
IComparable
是完全有意义的;我们要比较一下钥匙

人们使用和误用这种模式的其他方式有哪些

有关许多示例,请参见

为什么第一种方法不够完美

因为它不处理这两种情况:

首先,假设我们有一个多字典,但它不是从键到列表:

Dictionary<string, int[]>
字典

字典

字典
或者别的什么

第二,它也不处理这个案件

class MyList : List<int> {}
...
Dictionary<string, MyList>
class MyList:List{}
...
字典
尽管这种情况非常罕见;您不应该正常扩展
列表

为了实现最大的通用性,实现字典方法的正确方法是什么

这里有一个方法:

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();
}
公共静态bool为空(此IEnumerable items)
{
//练习:为什么这个实现不好?
//练习:你能改进它吗?
foreach(项目中的var项目)
返回false;
返回true;
}
公共静态bool为空(
这本字典(TKey)
其中TValue:IEnumerable
{
return!dictionary.ContainsKey(key)| | dictionary[key].IsEmpty();
}

为了更加通用,您可以使用
IDictionary
而不是
Dictionary

这样做有效吗?我不明白一个类型如何被约束到一个所述类型的列表中,但我不太熟悉泛型约束。约束只是将一个类型限制到一个具有特定实现(如接口或基类)的类型。您应该首先尝试以上两种方法,看看会发生什么情况。:)@鲁弗斯是绝对正确的;两个代码示例之间的区别在于第一个代码示例有效,第二个代码示例无效!编译器不会在声明站点给您一个错误,但是当您尝试实际调用该函数时,您会发现第二个根本不起作用。假设您尝试使用
List
TValue
调用函数。由于
列表
不是
列表
,因此它将不起作用。假设您尝试使用
int
TValue
调用函数;嗯,
int
不是
List
,所以这也失败了。这种约束在一些罕见和奇怪的情况下起作用,你应该避免这些罕见和奇怪的情况。有关此模式的更多想法以及为什么它是一个坏主意,请参见,无需编写
!A | A和B
。只要写
!A | | B
。如果!A是真的,那么我们不计算A&&B,如果!A是假的,那么A&&B是真的&&B就是B。这样行吗?我不明白一个类型如何被约束到一个所述类型的列表中,但我不太熟悉泛型约束。约束只是将一个类型限制到一个具有特定实现(如接口或基类)的类型。您应该首先尝试以上两种方法,看看会发生什么情况。:)@鲁弗斯是绝对正确的;两个代码示例之间的区别在于第一个代码示例有效,第二个代码示例无效!编译器不会在声明站点给您一个错误,但是当您尝试实际调用该函数时,您会发现第二个根本不起作用。假设你试着打电话给你