C#中索引的Typedef,带有静态类型检查,无运行时开销
使用具有复杂索引的多维数组是非常常见的情况。当所有索引都是int时,这真的很容易混淆和出错,因为您可以很容易地混淆列和行(或任何您拥有的),并且编译器无法识别问题。实际上,应该有两种类型的索引:行和列,但它不是在类型级别上表示的 下面是我想要的一个小例子:C#中索引的Typedef,带有静态类型检查,无运行时开销,c#,typechecking,static-typing,C#,Typechecking,Static Typing,使用具有复杂索引的多维数组是非常常见的情况。当所有索引都是int时,这真的很容易混淆和出错,因为您可以很容易地混淆列和行(或任何您拥有的),并且编译器无法识别问题。实际上,应该有两种类型的索引:行和列,但它不是在类型级别上表示的 下面是我想要的一个小例子: var table = new int[RowsCount,ColumnsCount]; Row row = 5; Column col = 10; int value = table[row, col]; public void Calc
var table = new int[RowsCount,ColumnsCount];
Row row = 5;
Column col = 10;
int value = table[row, col];
public void CalcSum(int[,] table, Column col)
{
int sum = 0;
for (Row r = 0; r < table.GetLength(0); r++)
{
sum += table[row, col];
}
return sum;
}
CalcSum(table, col); // OK
CalcSum(table, row); // Compile time error
var table=newint[rowsunt,columnsunt];
行=5;
列col=10;
int值=表[行,列];
公共void CalcSum(int[,]表,列col)
{
整数和=0;
for(行r=0;r
总结:
- 应静态检查索引是否混淆(类型检查)
- 重要它们应该具有运行时效率,因为将整数包装到包含索引的自定义对象,然后再将其展开,对性能来说是不好的
- 它们应该隐式转换为int,以便在本机多维数组中用作索引
有没有办法做到这一点?完美的解决方案是类似于
typedef
的东西,它充当编译时检查功能,仅编译为平面整数。使用x64抖动时,速度只会降低2倍。它生成有趣的优化代码。使用结构的循环如下所示:
00000040 mov ecx,1
00000045 nop word ptr [rax+rax+00000000h]
00000050 lea eax,[rcx-1]
s.Idx = j;
00000053 mov dword ptr [rsp+30h],eax
00000057 mov dword ptr [rsp+30h],ecx
0000005b add ecx,2
for (int j = 0; j < 100000000; j++) {
0000005e cmp ecx,5F5E101h
00000064 jl 0000000000000050
现在您将看到不再有任何区别。如果两种类型都隐式转换为整数,编译器如何知道它是错误的?它将推断出其中任何一个是正确的。将其包装到
结构中有什么错?即使隐式转换为int方法调用参数,也可以执行类型检查。在结构中包装的速度比int慢2倍(我刚刚用一个合成测试进行了检查)。你的测试是什么样子的?这里是:怪异。。我从你的测试中得到了几乎相同的速度。2319ms->int,2347ms->struct.Good catch,missing Console.Write(“Sum={0}”,Sum)是一个愚蠢的错误。现在,你会发现它们已经没有区别了。
确实有。557毫秒对445毫秒-速度降低25%。我不打算追逐“25%=2倍减速”的说法。让你的情况与微软,唯一可以真正改变抖动。在connect.microsoft.com上提交错误报告,并确保提供良好的证据。
000000af xor eax,eax
000000b1 add eax,4
for (int j = 0; j < 100000000; j++) {
000000b4 cmp eax,5F5E100h
000000b9 jl 00000000000000B1
Console.Write("Sum = {0} ", sum);