Mapping a ulong to a long in C#?
我正在尝试将ulong映射为long(反之亦然),并将uint映射为int(反之亦然),如下所示-为了将值保存在具有签名类型的MS-SQL数据库中 仅整数和biginteger。
我这样做是因为我必须检查(在数据库中)数字(uint,ulong)是否在uint / ulong范围(IPs-v4和v6)中的某个范围内;实际上ulong实际上是一个uint128,由 两个乌龙)。
有没有比我在这里的代码更有效的方法来完成此操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | 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); } |
要从
1 2 3 4 5 6 7 8 9 |
死灵法术。
基于Tanner Swett的答案的通用答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | private static class Number< T > { 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< T >() { return (T)GetConstValue(typeof(T),"MinValue"); } private static T GetMaxValue< T >() { return (T)GetConstValue(typeof(T),"MaxValue"); } private static System.Func<T, T, T> CompileAdd< T >() { // 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<T, T, T> add = System.Linq.Expressions.Expression.Lambda<System.Func<T, T, T>> (body, paramA, paramB).Compile(); return add; } private static System.Func<T, T, T> CompileSubtract< T >() { // 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<T, T, T> subtract = System.Linq.Expressions.Expression.Lambda<System.Func<T, T, T>> (body, paramA, paramB).Compile(); return subtract; } public static T MinValue = GetMinValue< T >(); public static T MaxValue = GetMaxValue< T >(); public static System.Func<T, T, T> Add = CompileAdd< T >(); public static System.Func<T, T, T> Subtract = CompileSubtract< T >(); } public static TSigned MapUnsignedToSigned<TUnsigned, TSigned>(TUnsigned ulongValue) { TSigned signed = default(TSigned); unchecked { signed = Number<TSigned>.Add((TSigned)(dynamic)ulongValue, Number<TSigned>.MinValue); } return signed; } public static TUnsigned MapSignedToUnsigned<TSigned, TUnsigned>(TSigned longValue) { TUnsigned unsigned = default(TUnsigned); unchecked { unsigned = (TUnsigned)(dynamic) Number<TSigned> .Subtract(longValue, Number<TSigned>.MinValue); } return unsigned; } |
当量:
1 2 3 4 5 6 7 8 9 10 11 12 | // return MapUnsignedToSigned<ulong, long>(ulongValue); private static long MapULongToLong(ulong ulongValue) { return unchecked((long)ulongValue + long.MinValue); } // return MapSignedToUnsigned<long, ulong>(longValue); private static ulong MapLongToUlong(long longValue) { return unchecked((ulong)(longValue - long.MinValue)); } |
尽管坦纳·斯威特是正确的。 一个更好而又肮脏的解决方案是告诉.net将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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; } } } |
通过将实体框架POCO设置为使用显示的属性,可以控制字段映射到的内存地址。
因此,永远不会发生转换。
此代码比Tanner Swett的代码快100%。