C# 将对象转换为数字类型并检查值

C# 将对象转换为数字类型并检查值,c#,.net,windows-8,windows-store-apps,C#,.net,Windows 8,Windows Store Apps,我正在为Windows应用商店应用程序编写一个使用.NET的框架。对于自定义格式化程序字符串格式(字符串格式,params object[]args),我有以下代码: public static bool IsExactlyOne(object n) { if (n is Int16) { return (Int16)n == 1; } if (n is int) // Int32 { return (int)n == 1;

我正在为Windows应用商店应用程序编写一个使用.NET的框架。对于自定义格式化程序
字符串格式(字符串格式,params object[]args)
,我有以下代码:

public static bool IsExactlyOne(object n)
{
    if (n is Int16)
    {
        return (Int16)n == 1;
    }
    if (n is int) // Int32
    {
        return (int)n == 1;
    }
    if (n is long) // Int64
    {
        return (long)n == 1L;
    }
    if (n is UInt16)
    {
        return (UInt16)n == 1U;
    }
    if (n is uint) // UInt32
    {
        return (uint)n == 1U;
    }
    if (n is ulong) // UInt64
    {
        return (ulong)n == 1UL;
    }
    if (n is byte)
    {
        return (byte)n == 1;
    }
    if (n is sbyte)
    {
        return (sbyte)n == 1;
    }
    if (n is float)
    {
        return (float)n == 1.0F;
    }
    if (n is double)
    {
        return (double)n == 1.0D;
    }
    if (n is decimal)
    {
        return (decimal)n == 1.0M;
    }

    throw new ArgumentException("Unsupported type");
}

如你所见,它相当冗长。有什么方法可以简化这一点吗?请注意:
IConvertible
不适用于Windows应用商店应用程序。

如果出现以下情况,如何使用字典来避免

var dic = new Dictionary<Type, Func<object, bool>>()
                    {
                        {typeof(Int16), a => (Int16)a == 1},
                        {typeof(int), a => (int)a == 1},
                         ....
                    };

return dic[n.GetType()](n);
好了:

public static bool IsExactlyOne(object n)
{
bool result = false;
try
{
result = Convert.ToDouble(n) == 1.0;
}
catch
{
}
return result;
}

请看一下被接受的答案


这应该很好:

    bool IsExactlyOne(object n)
    {
        int i;
        int.TryParse(n.ToString(), out i);
        return i == 1;
    }
除非处理像1.000000000000001这样的高精度数字,这是OP版本中已经存在的问题


处理高精度的唯一方法是显式使用十进制。

使用
对象
有什么具体原因吗?我会使用
ulong
double
来代替,因为隐式转换应该完成其余的工作?有时你别无选择(例如IValueConverter)@Mario:It's
object
,因为这个函数是一个自定义格式化程序的一部分,它遵循.NET样式
Format(string Format,params object[]args)
我想你最好还是保持原样吧。有太多的角落案例要检查你是否尝试了比这个短的东西。@Sebastian Negraszus:你试过我答案中的代码了吗?动态解决方案是一个很好的解决方案。dictionary one对于这样一个平凡的需求来说真的很糟糕而且没有必要……动态的
解决方案看起来很有前途。我以前从未使用过dynamic。您的代码是否有和我的代码不同的行为?对于添加的错误处理,若为false,您可以返回tryparse的结果;)对于双精度值1.0000000000000001,这不起作用,因为
ToString
只打印出前15位。@juharr ok,但1.0000000000000001与1真的不同吗?@AndersonSilva是的,它是。在OP的当前代码中,返回false,但在您的中,返回true。@juharr OP的当前代码也有同样的问题。在这种情况下,它也返回true。问题是当值被装箱到对象中时,它也会被舍入。这对double不起作用,因为它们会被舍入。OP的代码正在检查是否只有一个,如果我将其转换为
int
。酷。将其更改为ToDouble(),有一些十进制值对
ToDouble
不起作用,例如
0.99999999999999999999m
。也许
ToDecimal
可以全面发挥作用。
string value = "123.3";
double num;
if (!double.TryParse(value, out num))
  throw new InvalidOperationException("Value is not a number.");
    bool IsExactlyOne(object n)
    {
        int i;
        int.TryParse(n.ToString(), out i);
        return i == 1;
    }