Wed*_*dge 14 c# generics .net-4.0
为什么Equals方法从泛型方法中返回不同的结果?我认为这里有一些我不明白的自动拳击.
这是一个使用.net 3.5或4.0重现行为的示例:
static void Main(string[] args)
{
TimeZoneInfo tzOne = TimeZoneInfo.Local;
TimeZoneInfo tzTwo = TimeZoneInfo.FindSystemTimeZoneById(tzOne.StandardName);
Console.WriteLine(Compare(tzOne, tzTwo));
Console.WriteLine(tzOne.Equals(tzTwo));
}
private static Boolean Compare<T>(T x, T y)
{
if (x != null)
{
return x.Equals(y);
}
return y == null;
}
Run Code Online (Sandbox Code Playgroud)
输出:
False
True
Run Code Online (Sandbox Code Playgroud)
编辑:此代码按预期工作,没有多少妥协:
private static Boolean Compare<T>(T x, T y)
{
if (x != null)
{
if (x is IEquatable<T>)
{
return (x as IEquatable<T>).Equals(y);
}
return x.Equals(y);
}
return y == null;
}
Run Code Online (Sandbox Code Playgroud)
跟进:我通过MS Connect提交了一个错误,它已被解决为已修复,因此可能会在下一版本的.net框架中修复.如果可用,我会更新更多细节.
PS:这似乎是在.net 4.0及更高版本中修复的(通过查看mscorlib中TimeZoneInfo的反汇编).
Dan*_*ant 13
TimeZoneInfo不会覆盖Object Equals方法,因此它调用默认的Object Equals,这显然不能按预期工作.我会认为这是TimeZoneInfo中的一个错误.这应该工作:
private static Boolean Compare<T>(T x, T y)
where T: IEquatable<T>
{
if (x != null)
{
return x.Equals(y);
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
以上将导致它调用Equals<T>,这是你上面调用的方法(它隐含地优先使用泛型调用,因为它比参数类型更具体于参数类型;但是在泛型方法中,它无法成为确定存在这样的通用Equals,因为没有约束保证这一点).
FWIW,在单声道2.8+上,两个返回值均为False,输出
False
False
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,来自VS2010的csc.exe产生了不同的结果,实际上,输出:
False
True
Run Code Online (Sandbox Code Playgroud)
甚至更有趣的是,这个问题似乎不与所产生的IL代码,但与框架实现/ JIT引擎;
False/False单声道编译版本一样,使用Mono VM执行MS编译的图像False/TrueMS编译版本一样,使用MS VM执行Mono编译的图像为了您的兴趣,以下是Microsoft的CSC.exe编译器(csc.exe /optimize+ test.cs)的反汇编:
.method private static hidebysig
default bool Compare<T> (!!T x, !!T y) cil managed
{
// Method begins at RVA 0x2087
// Code size 30 (0x1e)
.maxstack 8
IL_0000: ldarg.0
IL_0001: box !!0
IL_0006: brfalse.s IL_001c
IL_0008: ldarga.s 0
IL_000a: ldarg.1
IL_000b: box !!0
IL_0010: constrained. !!0
IL_0016: callvirt instance bool object::Equals(object)
IL_001b: ret
IL_001c: ldc.i4.0
IL_001d: ret
} // end of method Program::Compare
Run Code Online (Sandbox Code Playgroud)
和Mono的gmcs.exe编译器(dmcs -optimize+ test.cs):
.method private static hidebysig
default bool Compare<T> (!!T x, !!T y) cil managed
{
// Method begins at RVA 0x212c
// Code size 33 (0x21)
.maxstack 4
IL_0000: ldarg.0
IL_0001: box !!0
IL_0006: brfalse IL_001f
IL_000b: ldarga.s 0
IL_000d: ldarg.1
IL_000e: box !!0
IL_0013: constrained. !!0
IL_0019: callvirt instance bool object::Equals(object)
IL_001e: ret
IL_001f: ldc.i4.0
IL_0020: ret
} // end of method Program::Compare
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
384 次 |
| 最近记录: |