字典序比较.net类库自带有string.CompareOrdinal,不过不支持char*。有时候为了效率不想重复fixed同一个字符串,而却有时候char*是stackalloc new出来的,更加不适应。还是那句话,自食其力吧。
public static unsafe int cmp(string left, string right) { if (left != null && right != null) { int length = left.Length <= right.Length ? left.Length : right.Length; for (int index = 0, endIndex = Math.Min(length, 4); index != endIndex; ++index) { int value = left[index] - right[index]; if (value != 0) return value; } if ((length -= 4) > 0) { fixed (char* leftFixed = left, rightFixed = right) { int value = Cmp(leftFixed + 4, rightFixed + 4, length); if (value != 0) return value; } } return left.Length - right.Length; } if (left == right) return 0; return left != null ? 1 : -1; } private static unsafe int Cmp(char* left, char* right, int length) { while (length >= 8) { if (((*(uint*)left ^ *(uint*)right) | (*(uint*)(left + 4) ^ *(uint*)(right + 4)) | (*(uint*)(left + 8) ^ *(uint*)(right + 8)) | (*(uint*)(left + 12) ^ *(uint*)(right + 12))) != 0) { if (((*(uint*)left ^ *(uint*)right) | (*(uint*)(left + 4) ^ *(uint*)(right + 4))) == 0) { left += 8; right += 8; } if (*(uint*)left == *(uint*)right) { left += 4; right += 4; } int value = (int)*(ushort*)left - *(ushort*)right; return value == 0 ? (int)*(ushort*)(left += 2) - *(ushort*)(right += 2) : value; } length -= 8; left += 16; right += 16; } if ((length & 4) != 0) { if (((*(uint*)left ^ *(uint*)right) | (*(uint*)(left + 4) ^ *(uint*)(right + 4))) != 0) { if ((*(uint*)left ^ *(uint*)right) == 0) { left += 4; right += 4; } int value = (int)*(ushort*)left - *(ushort*)right; return value == 0 ? (int)*(ushort*)(left += 2) - *(ushort*)(right += 2) : value; } left += 8; right += 8; } if ((length & 2) != 0) { int code = (int)*(ushort*)left - *(ushort*)right; if (code != 0) return code; code = (int)*(ushort*)(left + 2) - *(ushort*)(right + 2); if (code != 0) return code; left += 4; right += 4; } return (length & 1) == 0 ? 0 : ((int)*(ushort*)left - *(ushort*)right); }
Release实测,运行效率不算很糟糕,一般情况还能比string.CompareOrdinal快20%-40%,关键是满足了新的功能需求,提高了其他程序的运行效率。