简单的方法来检查原始数据类型是否为"可以安全地放入原始数据类型"(假设两者的签名相同)

本文关键字:原始 数据类型 quot 假设 是否 检查 方法 安全 简单 | 更新日期: 2023-09-27 18:02:09

给定此函数:

bool WillDataTypeFit(Type typeToCheck, Type typeToFitInto)
{
    bool bWillFit = false;
    // Psedocode
    // IF typeToCheck is NOT the same as typeToFitInfo
    //    IF typeToCheck && typeToFitInfo are signed
    //       Check for signed fit
    //    ELSE IF typeToCheck && typeToFitInfo are unsigned
    //       Check for unsigned fit
    // ELSE
    //    bWillFit = true;
    return (bWillFit);
}

是否有一个简单的方法来看看typeToCheck是否可以安全地适合typeToFitInto ?

我关心的是原始数据类型,不包括DateSpan, DateTime, bool, decimal, string, char, object

也就是signed/unsigned int float double

编辑:

"Fit into"意味着我可以安全地将typeToCheck的最大/最小值转换为typeToFitInto的类型,但是在此检查时,我没有任何值可以转换,所以我试图简单地检查数据类型

EDIT2:

我已经意识到这个问题通常是有缺陷的,因为没有一个值,你不能保证像一个正的sbyte适合于byte,我编辑了这个问题,所以只有当两种数据类型具有相同的签名时才会评估检查

简单的方法来检查原始数据类型是否为"可以安全地放入原始数据类型"(假设两者的签名相同)

据我所知没有简单的方法。您将需要这样的内容:

bool WillDataTypeFit(Type typeToCheck, Type typeToFitInto)
{
    if (typeToCheck.Equals(typeToFitInto))
    {
        return true;
    }
    else if (typeToCheck == typeof(sbyte))
    {
        if (typeToFitInto == typeof(short))
            return true;
        else if (typeToFitInto == typeof(int))
            return true;
        else if (typeToFitInto == typeof(long))
            return true;
        else if (typeToFitInto == typeof(float))
            return true;
        else if (typeToFitInto == typeof(double))
            return true;
        else if (typeToFitInto == typeof(decimal))
            return true;
        else
            return false;
    }
    else if (typeToCheck == typeof(byte))
    {
        if (typeToFitInto == typeof(short))
            return true;
        else if (typeToFitInto == typeof(ushort))
            return true;
        else if (typeToFitInto == typeof(int))
            return true;
        else if (typeToFitInto == typeof(uint))
            return true;
        else if (typeToFitInto == typeof(long))
            return true;
        else if (typeToFitInto == typeof(ulong))
            return true;
        else if (typeToFitInto == typeof(float))
            return true;
        else if (typeToFitInto == typeof(double))
            return true;
        else if (typeToFitInto == typeof(decimal))
            return true;
        else
            return false;
    }
    else if (typeToCheck == typeof(ushort))
    {
        if (typeToFitInto == typeof(int))
            return true;
        else if (typeToFitInto == typeof(uint))
            return true;
        else if (typeToFitInto == typeof(long))
            return true;
        else if (typeToFitInto == typeof(ulong))
            return true;
        else if (typeToFitInto == typeof(float))
            return true;
        else if (typeToFitInto == typeof(double))
            return true;
        else if (typeToFitInto == typeof(decimal))
            return true;
        else
            return false;
    }
    else if (typeToCheck == typeof(short))
    {
        if (typeToFitInto == typeof(int))
            return true;
        else if (typeToFitInto == typeof(long))
            return true;
        else if (typeToFitInto == typeof(float))
            return true;
        else if (typeToFitInto == typeof(double))
            return true;
        else if (typeToFitInto == typeof(decimal))
            return true;
        else
            return false;
    }
    else if (typeToCheck == typeof(uint))
    {
        if (typeToFitInto == typeof(long))
            return true;
        else if (typeToFitInto == typeof(ulong))
            return true;
        else if (typeToFitInto == typeof(float))
            return true;
        else if (typeToFitInto == typeof(double))
            return true;
        else if (typeToFitInto == typeof(decimal))
            return true;
        else
            return false;
    }
    else if (typeToCheck == typeof(int))
    {
        if (typeToFitInto == typeof(long))
            return true;
        else if (typeToFitInto == typeof(float))
            return true;
        else if (typeToFitInto == typeof(double))
            return true;
        else if (typeToFitInto == typeof(decimal))
            return true;
        else
            return false;
    }
    else if (typeToCheck == typeof(long) || typeToCheck == typeof(ulong))
    {
        if (typeToFitInto == typeof(float))
            return true;
        else if (typeToFitInto == typeof(double))
            return true;
        else if (typeToFitInto == typeof(decimal))
            return true;
        else
            return false;
    }
    else if (typeToCheck == typeof(float))
    {
        if (typeToFitInto == typeof(double))
            return true;
        else
            return false;
    }
    else
    {
        return false;
    }
}

我相信这是详尽的数字类型,但你可以在这里检查隐式数字转换

如果您可以将自己限制为只使用结构体,则可以滥用dynamic关键字进行检查。

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(WillDataTypeFit<short, int>());
        Console.WriteLine(WillDataTypeFit<int, short>());
    }
    static bool WillDataTypeFit<TTypeToCheck, TTypeToFitInto>()
        where TTypeToCheck : struct
        where TTypeToFitInto : struct 
    {
        TTypeToCheck typeToCheck = default(TTypeToCheck);
        dynamic test = typeToCheck;
        try
        {
            TTypeToFitInto toFitInto = test;
        }
        catch (Exception)
        {
            return false;
        }
        return true;
    }
}

如果你使用float, byte等类型,你总是可以使用"sizeof "。考虑:

Console.WriteLine(sizeof(bool)); // 1
Console.WriteLine(sizeof(byte)); // 1
Console.WriteLine(sizeof(short)); // 2
Console.WriteLine(sizeof(int)); // 4
Console.WriteLine(sizeof(long)); // 8

我可以用Marshall。struct的SizeOf,例如

private struct Temp
    {
        public int a { get; set; }
        public int b { get; set; }
        public int c { get; set; }
        public Temp(int a, int b, int c)
        {
            this.a = a;
            this.b = b;
            this.c = c;
        }
    }
Console.WriteLine(Marshal.SizeOf(new Temp(1, 2, 3))); // 12

所以你可以用这个来做比较(取决于你想比较的类型;这绝对适用于像结构体、整型等值类型,但对于纯托管引用类型,它似乎会崩溃;你肯定会不能在List类上执行sizeof,因为它的大小不一定是静态的)。

为了更直接地解决你的问题,请特别注意sizeof(int) x "适合" y当且仅当sizeof(x) <= sizeof(y)

顺便说一下,在这种情况下,"适合"是一个反对称的、自反的和传递的关系,所以它可以被认为是。net类型上的偏序。(这不是一个完整的顺序,因为它没有对引用类型进行排序)。

有两种可行的方法:

  1. 查看类型是否可以隐式浇注,就像这篇文章的讨论一样
  2. 使用反射来比较数值类型的静态MinValue和MaxValue属性。
  3. 按照前面的答案建议使用硬编码字典或查找。如果你关心的唯一类型集是(int, int, float, double, long, ulong),这可能是最简单和最高效的。