happyhippy

这个世界的问题在于聪明人充满疑惑,而傻子们坚信不疑。--罗素
   1: public static bool IsDefault<T>(this T value) 
   2: {
   3:       //...
   4: }

1. ==的问题

    如果用==直接判断(default(T) == value),编译时会提示错误:Error CS0019: 运算符“==”无法应用于“T”和“T”类型的操作数 (CS0019)。

 

2. object.Equals的问题

    object提供了一个静态方法,可用于比较两个对象是否相等:

   1: public static bool Equals(object objA, object objB)
   2: {
   3:     if (objA == objB)
   4:     {
   5:         return true;
   6:     }
   7:     if (objA == null || objB == null)
   8:     {
   9:         return false;
  10:     }
  11:     return objA.Equals(objB);
  12: }

   但是该方法接收的是引用类型的实例,如果传入的是值类型(譬如int、enum、struct等),则会对值类型进行装箱(boxing)。
   

3. EqualityComparer<T>.Default.Equals

    最给力的方法,还是用EqualityComparer<T>.Default.Equals,

   1: public static bool IsDefault<T>(this T value) 
   2: {
   3:      return EqualityComparer<T>.Default.Equals(value, default(T)); 
   4: }

   其实现了一个默认的比较器,可以比较Byte、Nullable<T>、Enum、Object、以及实现了IEquatable<T>接口(譬如int、bool、自定义类型等)的所有类型,可以用ILSpy来查看该类型的具体实现:

   1: private static EqualityComparer<T> defaultComparer;
   2: public static EqualityComparer<T> Default
   3: {
   4:     [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), SecuritySafeCritical]
   5:     get
   6:     {
   7:         EqualityComparer<T> equalityComparer = EqualityComparer<T>.defaultComparer;
   8:         if (equalityComparer == null)
   9:         {
  10:             equalityComparer = EqualityComparer<T>.CreateComparer();
  11:             EqualityComparer<T>.defaultComparer = equalityComparer;
  12:         }
  13:         return equalityComparer;
  14:     }
  15: }
  16: [SecuritySafeCritical]
  17: private static EqualityComparer<T> CreateComparer()
  18: {
  19:     RuntimeType runtimeType = (RuntimeType)typeof(T);
  20:     if (runtimeType == typeof(byte))//其实byte也实现了IEquatable<Byte>,不知道为神马要把byte单独提出来???
  21:     {
  22:         return (EqualityComparer<T>)new ByteEqualityComparer();
  23:     }
  24:     if (typeof(IEquatable<T>).IsAssignableFrom(runtimeType))//如果类型实现了IEquatable<T>,则在运行时构造GenericEqualityComparer<T>,调用类型自身提供(重写)的equals方法。
  25:     {
  26:         return (EqualityComparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericEqualityComparer<int>), runtimeType);
  27:     }
  28:     if (runtimeType.IsGenericType && runtimeType.GetGenericTypeDefinition() == typeof(Nullable))
  29:     {
  30:         RuntimeType runtimeType2 = (RuntimeType)runtimeType.GetGenericArguments()[0];
  31:         if (typeof(IEquatable).MakeGenericType(new Type[]
  32:         {
  33:             runtimeType2
  34:         }).IsAssignableFrom(runtimeType2))
  35:         {
  36:             return (EqualityComparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableEqualityComparer<int>), runtimeType2);
  37:         }
  38:     }
  39:     if (runtimeType.IsEnum && Enum.GetUnderlyingType(runtimeType) == typeof(int))
  40:     {
  41:         return (EqualityComparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer<int>), runtimeType);
  42:     }
  43:     return new ObjectEqualityComparer<T>();
  44: }

 

4. ILSpy比JustDecompile强大呀

4.1. ObjectEqualityComparer<T>.Equals方法的比较

image

clip_image001

 

4.2. EqualityComparer<T>.CreateComparer()方法:

image

各种杯具。。。

 

posted on 2011-06-21 23:00  Silent Void  阅读(7103)  评论(1编辑  收藏  举报