gpt4 book ai didi

c# - 此搜索方法中 IComparable 和 IComparable 的区别

转载 作者:太空狗 更新时间:2023-10-30 00:01:20 25 4
gpt4 key购买 nike

我知道 IComparable 之间有很大的区别和 IComparable<T>一般情况下,请参阅 this , 但在这种搜索方法中,它不会有任何区别,还是会这样?

public static int Search<T>(List<T> a, T target) where T : IComparable
{
for (int i = 0; i < a.Count; i++)
{
if (target.CompareTo(a[i]) == 0)
return i;
}
return -1;
}

相比于:

public static int Search<T>(List<T> a, T target) where T : IComparable<T>
{
...
}

两者都可以工作并给出相同的结果吗?

最佳答案

Both will work and give the same result, or not?

让我们看看编译器为这两种搜索方法发出的结果:

Search:
IL_0000: ldc.i4.0
IL_0001: stloc.0 // i
IL_0002: br.s IL_0025
IL_0004: ldarga.s 01
IL_0006: ldarg.0
IL_0007: ldloc.0 // i
IL_0008: callvirt 06 00 00 0A
IL_000D: box 03 00 00 1B <---- Notice this!
IL_0012: constrained. 03 00 00 1B
IL_0018: callvirt System.IComparable.CompareTo
IL_001D: brtrue.s IL_0021
IL_001F: ldloc.0 // i
IL_0020: ret
IL_0021: ldloc.0 // i
IL_0022: ldc.i4.1
IL_0023: add
IL_0024: stloc.0 // i
IL_0025: ldloc.0 // i
IL_0026: ldarg.0
IL_0027: callvirt 08 00 00 0A
IL_002C: blt.s IL_0004
IL_002E: ldc.i4.m1
IL_002F: ret

SearchGeneric:
IL_0000: ldc.i4.0
IL_0001: stloc.0 // i
IL_0002: br.s IL_0020
IL_0004: ldarga.s 01
IL_0006: ldarg.0
IL_0007: ldloc.0 // i
IL_0008: callvirt 06 00 00 0A
IL_000D: constrained. 03 00 00 1B
IL_0013: callvirt 09 00 00 0A
IL_0018: brtrue.s IL_001C
IL_001A: ldloc.0 // i
IL_001B: ret
IL_001C: ldloc.0 // i
IL_001D: ldc.i4.1
IL_001E: add
IL_001F: stloc.0 // i
IL_0020: ldloc.0 // i
IL_0021: ldarg.0
IL_0022: callvirt 08 00 00 0A
IL_0027: blt.s IL_0004
IL_0029: ldc.i4.m1
IL_002A: ret

如果仔细观察,您会发现主要区别在于 Search 中的每次调用,在调用 CompareTo 之前都必须将value(这在 box 操作中值得注意),因为非通用版本接受 object 类型。

让我们尝试使用 value type 来分析两者之间的性能差异.我要使用 BenchmarkDotNet ,这是一个小型(而且非常棒)基准测试框架,负责 JITing、CPU 预热等。

测试:

[BenchmarkTask(platform: BenchmarkPlatform.X86)]
[BenchmarkTask(platform: BenchmarkPlatform.X64)]
public class Test
{
private readonly List<int> list = Enumerable.Range(0, 1000000).ToList();

[Benchmark]
public void TestSearch()
{
Search(list, 999999);
}

[Benchmark]
public void TestSearchGeneric()
{
SearchGeneric(list, 999999);
}

public static int Search<T>(List<T> a, T target) where T : IComparable
{
for (int i = 0; i < a.Count; i++)
{
if (target.CompareTo(a[i]) == 0)
return i;
}
return -1;
}
public static int SearchGeneric<T>(List<T> a, T target) where T : IComparable<T>
{
for (int i = 0; i < a.Count; i++)
{
if (target.CompareTo(a[i]) == 0)
return i;
}
return -1;
}
}

结果:

***** Competition: Finish  *****

BenchmarkDotNet=v0.7.8.0
OS=Microsoft Windows NT 6.1.7601 Service Pack 1
Processor=Intel(R) Core(TM) i7-4600U CPU @ 2.10GHz, ProcessorCount=4
HostCLR=MS.NET 4.0.30319.42000, Arch=32-bit
Type=Test Mode=Throughput Jit=HostJit .NET=HostFramework


Method | Platform | AvrTime | StdDev | op/s |
------------------ |--------- |----------- |---------- |------- |
TestSearch | X64 | 35.8065 ms | 3.3439 ms | 27.93 |
TestSearchGeneric | X64 | 4.6427 ms | 0.3075 ms | 215.40 |
TestSearch | X86 | 26.4876 ms | 1.4776 ms | 37.75 |
TestSearchGeneric | X86 | 6.6500 ms | 0.1664 ms | 150.38 |

***** Competition: End *****

看到导致装箱操作的非泛型方法在 x86 上慢 4 倍多,在 x64 上慢 8 倍多。这可能会影响您的应用程序性能。

我通常不会使用非泛型 IComparable,它主要是为了向后兼容泛型之前的日子。请注意,另一个同样重要的因素是您通过泛型获得的类型安全性。

关于c# - 此搜索方法中 IComparable 和 IComparable<T> 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34242746/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com