在C#中将ulong映射为long?

时间:2016-12-01 00:20:48

标签: c# .net data-conversion uint ulong

我正在尝试将ulong映射到long(反之亦然),并将uint映射到int(反之亦然),如下所示 - 以便将值保存在MS-SQL数据库中仅使用signed类型integer和biginteger。

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

UlongToLong

UIntToInt

有没有比我在这里的代码更有效的方法来实现这个目标:

echo "This is the value: " + PRODUCTION_MAILS

3 个答案:

答案 0 :(得分:6)

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

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的逻辑完全类似。

答案 1 :(得分:0)

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

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;
}

当量:

// 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));
}

答案 2 :(得分:-1)

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

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%。