[英]Typedef for indexes in C# with static type checking without runtime overhead
使用具有復雜索引的多維數組是很常見的情況。 當所有索引都是整數時,這真的很容易混淆,並且容易出錯,因為您可以輕松地混合列和行(或您所擁有的任何東西),並且編譯器無法識別問題。 實際上,應該有兩種類型的索引:行和列,但是它不是在類型級別上表示的。
這是我想要的一個小例子:
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
加起來:
有什么辦法可以做到這一點? 理想的解決方案是像typedef
這樣的東西,它僅用作編譯時檢查以編譯為平面int。
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
由於代碼不常見,因此需要一些注釋。 首先,偏移量為45的怪異NOP會在循環開始時對齊指令。 這使得偏移量為64的分支更快。 53處的指令看起來完全沒有必要。 您在這里看到的是循環展開 ,請注意5b處的指令如何將循環計數器加2。然而,優化器不夠智能,因此也看不到存儲區。
最重要的是,這里沒有ADD指令。 換句話說,該代碼實際上並沒有計算“ sum”的值。 這是因為在循環后沒有在任何地方使用它,優化器可以看到該計算是無用的,並將其完全刪除了。
在第二個循環中,它做得更好:
000000af xor eax,eax
000000b1 add eax,4
for (int j = 0; j < 100000000; j++) {
000000b4 cmp eax,5F5E100h
000000b9 jl 00000000000000B1
現在,它完全刪除了“求和”計算和“ i”變量分配。 它也可能刪除了整個for()循環,但是抖動優化器從未做到這一點,它假設延遲是有意的。
希望到目前為止,信息已經清楚了:避免根據人工基准進行假設,並且只能描述真實的代碼。 您可以通過實際顯示“ sum”的值來使其更真實,這樣優化器就不會丟棄計算。 在循環之后添加以下代碼行:
Console.Write("Sum = {0} ", sum);
現在,您將看到沒有任何區別了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.