【问题标题】:Convert object to number type and check value将对象转换为数字类型并检查值
【发布时间】:2013-01-15 10:52:30
【问题描述】:

我正在使用 .NET 为 Windows 应用商店应用程序编写一个 pluralization 框架。对于自定义格式化程序string Format(string format, 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 应用商店应用。

【问题讨论】:

  • 使用object 有什么具体原因吗?我会改用ulongdouble,因为隐式转换应该完成其余的工作?而且我不希望传递一个字符串、列表或其他东西。
  • 有时你别无选择(例如 IValueConverter)
  • @Mario:是object,因为这个函数是遵循.NET 风格Format(string format, params object[] args)的自定义格式化程序的一部分
  • 我认为你最好保持原样。有太多的极端情况需要检查你是否尝试比这更短的方法。
  • @Sebastian Negraszus:你试过我回答中的代码吗?

标签: c# .net windows-8 windows-store-apps


【解决方案1】:

如何使用字典来避免if

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

或使用dynamic:

public static bool IsExactlyOne(dynamic n)
{
    return n == 1;
}         

【讨论】:

  • 动态解法不错。对于如此平凡的要求,一本字典真的很糟糕而且没有必要......
  • dynamic 解决方案看起来很有希望。我以前从未使用过动态。是否存在您的代码与我的代码行为不同的极端情况?
【解决方案2】:

这应该可以正常工作:

    bool IsExactlyOne(object n)
    {
        int i;
        int.TryParse(n.ToString(), out i);
        return i == 1;
    }

除非处理像 1.000000000000001 这样的高精度数字,这是 OP 版本中已经存在的问题。

处理高精度的唯一方法是显式使用小数。

【讨论】:

  • 对于添加的错误处理,如果为 false,您可以返回 tryparse 的结果;)
  • 这不适用于双精度值 1.0000000000000001,因为 ToString 只打印前 15 位数字。
  • @juharr 好的,但 1.0000000000000001 真的与 1 不同吗?
  • @AndersonSilva 是的。在 OP 的当前代码中将返回 false,但在您的代码中将返回 true。
  • @juharr OP 的当前代码有同样的问题。在这种情况下,它也返回 true。问题是当值被装箱到对象中时也会被四舍五入。
【解决方案3】:

请查看接受的答案here

string value = "123.3";
double num;
if (!double.TryParse(value, out num))
  throw new InvalidOperationException("Value is not a number.");

【讨论】:

    【解决方案4】:

    你去吧:

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

    【讨论】:

    • 这不适用于双打,因为它们会四舍五入。 OP 的代码正在检查一个,如果我将它转换为 int,它不是一个。
    • 酷。将其更改为 ToDouble()
    • 有些十进制值 ToDouble 不适用于 0.99999999999999999999999999M。也许ToDecimal 可以全面发挥作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-13
    • 2018-06-25
    • 2011-10-20
    相关资源
    最近更新 更多