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方法的比较
4.2. EqualityComparer<T>.CreateComparer()方法:
各种杯具。。。