在C#中将ulong映射为long?

我试图将ulong映射到long(反之亦然),并将uint映射到int(反之亦然),如下所示 – 以便将值保存在带有签名类型的MS-SQL数据库中整数和大整数。

我这样做是因为我必须检查(在数据库中)一个数字(uint,ulong)是否在一堆uint / ulong范围内的哪个范围内(IPs-v4&v6;实际上ulong实际上是由uint128组成的两个ulongs)。

UlongToLong

UIntToInt

是否有更有效的方法来实现这一点,然后我在这里的代码:

public static ulong SignedLongToUnsignedLong(long signedLongValue) { ulong backConverted = 0; // map ulong to long [ 9223372036854775808 = abs(long.MinValue) ] if (signedLongValue < 0) { // Cannot take abs from MinValue backConverted = (ulong)System.Math.Abs(signedLongValue - 1); backConverted = 9223372036854775808 - backConverted - 1; } else { backConverted = (ulong)signedLongValue; backConverted += 9223372036854775808; } return backConverted; } public static long UnsignedLongToSignedLong(ulong unsignedLongValue) { // map ulong to long [ 9223372036854775808 = abs(long.MinValue) ] return (long) (unsignedLongValue - 9223372036854775808); } public static int UnsignedIntToSignedInt(uint unsignedIntValue) { // map uint to int [ 2147483648 = abs(long.MinValue) ] return (int)(unsignedIntValue - 2147483648); } public static uint SignedIntToUnsignedInt(int signedIntValue) { uint backConverted = 0; // map ulong to long [ 2147483648 = abs(long.MinValue) ] if (signedIntValue < 0) { // Cannot take abs from MinValue backConverted = (uint)System.Math.Abs(signedIntValue - 1); backConverted = 2147483648 - backConverted - 1; } else { backConverted = (uint)signedIntValue; backConverted += 2147483648; } return backConverted; } public static void TestLong() { long min_long = -9223372036854775808; long max_long = 9223372036854775807; ulong min_ulong = ulong.MinValue; // 0 ulong max_ulong = ulong.MaxValue; // 18446744073709551615 = (2^64)-1 long dbValueMin = UnsignedLongToSignedLong(min_ulong); long dbValueMax = UnsignedLongToSignedLong(max_ulong); ulong valueFromDbMin = SignedLongToUnsignedLong(dbValueMin); ulong valueFromDbMax = SignedLongToUnsignedLong(dbValueMax); System.Console.WriteLine(dbValueMin); System.Console.WriteLine(dbValueMax); System.Console.WriteLine(valueFromDbMin); System.Console.WriteLine(valueFromDbMax); } public static void TestInt() { int min_int = -2147483648; // int.MinValue int max_int = 2147483647; // int.MaxValue uint min_uint= uint.MinValue; // 0 uint max_uint = uint.MaxValue; // 4294967295 = (2^32)-1 int dbValueMin = UnsignedIntToSignedInt(min_uint); int dbValueMax = UnsignedIntToSignedInt(max_uint); uint valueFromDbMin = SignedIntToUnsignedInt(dbValueMin); uint valueFromDbMax = SignedIntToUnsignedInt(dbValueMax); System.Console.WriteLine(dbValueMin); System.Console.WriteLine(dbValueMax); System.Console.WriteLine(valueFromDbMin); System.Console.WriteLine(valueFromDbMax); } 

要从ulong映射到long ,请long.MinValue并添加long.MinValue 。 要从long返回到ulong ,请减去long.MinValue和cast。 在任何一种情况下,都使用未经检查的上下文,以便忽略溢出条件。

 public static long MapUlongToLong(ulong ulongValue) { return unchecked((long)ulongValue + long.MinValue); } public static ulong MapLongToUlong(long longValue) { return unchecked((ulong)(longValue - long.MinValue)); } 

uintint的逻辑完全相似。

虽然Tanner Swett是正确的。 一个更好,更脏的解决方案是告诉.net将ulong访问映射到相同的内存地址。 这将为您提供瞬时转换速度。

 void Main() { var foo = new Foo { Long = -1 }; Console.WriteLine(foo.ULong); } // Define other methods and classes here [StructLayout(LayoutKind.Explicit)] public class Foo { [FieldOffset(0)] private ulong _ulong; [FieldOffset(0)] private long _long; public long Long { get { return _long; } set { _long = value; } } public ulong ULong { get { return _ulong; } set { _ulong = value; } } } 

通过将entity frameworkPOCO设置为使用显示的属性,您可以控制字段映射到的内存地址。

因此,不会发生任何转换。

此代码比Tanner Swett快100%。

Necromancing。
基于Tanner Swett答案的通用答案:

 private static class Number { private static object GetConstValue(System.Type t, string propertyName) { System.Reflection.FieldInfo pi = t.GetField(propertyName, System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic ); return pi.GetValue(null); } private static T GetMinValue() { return (T)GetConstValue(typeof(T), "MinValue"); } private static T GetMaxValue() { return (T)GetConstValue(typeof(T), "MaxValue"); } private static System.Func CompileAdd() { // Declare the parameters System.Linq.Expressions.ParameterExpression paramA = System.Linq.Expressions.Expression.Parameter(typeof(T), "a"); System.Linq.Expressions.ParameterExpression paramB = System.Linq.Expressions.Expression.Parameter(typeof(T), "b"); // Add the parameters System.Linq.Expressions.BinaryExpression body = System.Linq.Expressions.Expression.Add(paramA, paramB); // Compile it System.Func add = System.Linq.Expressions.Expression.Lambda> (body, paramA, paramB).Compile(); return add; } private static System.Func CompileSubtract() { // Declare the parameters System.Linq.Expressions.ParameterExpression paramA = System.Linq.Expressions.Expression.Parameter(typeof(T), "a"); System.Linq.Expressions.ParameterExpression paramB = System.Linq.Expressions.Expression.Parameter(typeof(T), "b"); // Subtract the parameters System.Linq.Expressions.BinaryExpression body = System.Linq.Expressions.Expression.Subtract(paramA, paramB); // Compile it System.Func subtract = System.Linq.Expressions.Expression.Lambda> (body, paramA, paramB).Compile(); return subtract; } public static T MinValue = GetMinValue(); public static T MaxValue = GetMaxValue(); public static System.Func Add = CompileAdd(); public static System.Func Subtract = CompileSubtract(); } public static TSigned MapUnsignedToSigned(TUnsigned ulongValue) { TSigned signed = default(TSigned); unchecked { signed = Number.Add((TSigned)(dynamic)ulongValue, Number.MinValue); } return signed; } public static TUnsigned MapSignedToUnsigned(TSigned longValue) { TUnsigned unsigned = default(TUnsigned); unchecked { unsigned = (TUnsigned)(dynamic) Number .Subtract(longValue, Number.MinValue); } return unsigned; } 

当量:

 // return MapUnsignedToSigned(ulongValue); private static long MapULongToLong(ulong ulongValue) { return unchecked((long)ulongValue + long.MinValue); } // return MapSignedToUnsigned(longValue); private static ulong MapLongToUlong(long longValue) { return unchecked((ulong)(longValue - long.MinValue)); }