首页 > 解决方案 > C# 一般比较数字

问题描述

我正在编写一个函数,该函数采用许多原始类型并决定该数字支持的最小类型是什么:

public static Type GetSmallestType( decimal value )
{
  return
    value.CompareTo( sbyte.MinValue ) >= 0 && value.CompareTo( sbyte.MaxValue ) <= 0 ? typeof( sbyte ) :
    value.CompareTo( byte.MinValue ) >= 0 && value.CompareTo( byte.MaxValue ) <= 0 ? typeof( byte ) :
    value.CompareTo( short.MinValue ) >= 0 && value.CompareTo( short.MaxValue ) <= 0 ? typeof( short ) :
    value.CompareTo( ushort.MinValue ) >= 0 && value.CompareTo( ushort.MaxValue ) <= 0 ? typeof( ushort ) :
    value.CompareTo( int.MinValue ) >= 0 && value.CompareTo( int.MaxValue ) <= 0 ? typeof( int ) :
    value.CompareTo( uint.MinValue ) >= 0 && value.CompareTo( uint.MaxValue ) <= 0 ? typeof( uint ) :
    value.CompareTo( long.MinValue ) >= 0 && value.CompareTo( long.MaxValue ) <= 0 ? typeof( long ) :
    value.CompareTo( ulong.MinValue ) >= 0 && value.CompareTo( ulong.MaxValue ) <= 0 ? typeof( ulong ) :
    typeof( decimal );
}

// e.g. GetSmallestType( -10 ) == typeof( sbyte )

此实现有效,但我想避免为每个单独的类型使用重载方法,因为它会导致大量重复代码。

当我尝试将其转换为接受泛型参数的泛型函数时,它会抛出一个错误,指出Object must be of type Int32.

public static Type GetSmallestType<T>( T value )
  where T : struct, IComparable, IComparable<T>, IConvertible, IEquatable<T>, IFormattable
{ ... }

目标是将值转换为最小的可用类型(由上述方法返回)并将其存储在通用树节点中。然后这个问题就变成了能够比较所有原始类型的问题,无论是使用强制转换还是其他方法,因为许多原始类型不能直接比较。

这是一个(可能不必要的)内存优化问题,我正在尝试寻找乐趣。

标签: c#

解决方案


您可以将两者都转换为动态的。是的,它排序违背了使用泛型方法的目的,但如果类型是数字,它就可以工作。结构约束将有助于防止类被传递。

它看起来ulong不适用于这种方法,但其他一切都可以。

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(GetSmallestType(100)); // System.SByte
        Console.WriteLine(GetSmallestType(200)); // System.Byte
        Console.WriteLine(GetSmallestType(30_000)); // System.Int16
        Console.WriteLine(GetSmallestType(60_000)); // System.UInt15
        Console.WriteLine(GetSmallestType(100_000)); // System.Int32
        Console.WriteLine(GetSmallestType(4_000_000_000)); // System.UInt23
        Console.WriteLine(GetSmallestType(100_000_000_000)); // System.Int64
        Console.WriteLine(GetSmallestType(20_000_000_000_000_000_000m)); // System.Decimal
    }

    public static Type GetSmallestType<T>(T propertyValue)
        where T : struct
    {
        dynamic value = propertyValue;

        return
            value >= (dynamic)sbyte.MinValue && value <= (dynamic)sbyte.MaxValue ? typeof(sbyte) :
            value >= (dynamic)byte.MinValue && value <= (dynamic)byte.MaxValue ? typeof(byte) :
            value >= (dynamic)short.MinValue && value <= (dynamic)short.MaxValue ? typeof(short) :
            value >= (dynamic)ushort.MinValue && value <= (dynamic)ushort.MaxValue ? typeof(ushort) :
            value >= (dynamic)int.MinValue && value <= (dynamic)int.MaxValue ? typeof(int) :
            value >= (dynamic)uint.MinValue && value <= (dynamic)uint.MaxValue ? typeof(uint) :
            value >= (dynamic)long.MinValue && value <= (dynamic)long.MaxValue ? typeof(long) :
            typeof(decimal);
    }
}

推荐阅读