C# 3.0 C#为什么可以';UInt32不能像UInt64那样拆箱吗?

C# 3.0 C#为什么可以';UInt32不能像UInt64那样拆箱吗?,c#-3.0,.net-micro-framework,C# 3.0,.net Micro Framework,考虑: object o = 123456U; ulong l = (ulong) o; // fails 但这是: object o = 123456U; ulong l = (ulong) (uint) o; // succeeds 我真正的问题是,我希望有一个函数,根据参数类型,以不同的方式处理它们。例如: void foo(object o) { switch (Type.GetTypeCode(o.GetType())) { case TypeCode.UInt3

考虑:

object o = 123456U;
ulong l = (ulong) o; // fails
但这是:

object o = 123456U;
ulong l = (ulong) (uint) o; // succeeds
我真正的问题是,我希望有一个函数,根据参数类型,以不同的方式处理它们。例如:

void foo(object o)
{
switch (Type.GetTypeCode(o.GetType()))
   {
      case TypeCode.UInt32:
      case TypeCode.UInt64:
      ulong l = (ulong) o;
      RunUnsignedIntVersion(l);
      break;
      case TypeCode.Int32:
      case TypeCode.Int64:
      long n = (long) o;
      RunSignedVersion(n);
      break;
   }
}
您无法拨打以下电话:

foo(123456U);
foo(123456);
我知道使用泛型有很多方法可以做到这一点。但我使用的是.net微框架,不支持泛型。但支持任何C#3.0编译器特有的功能,包括匿名函数

编辑我希望避免单独处理每种类型。是否有一种方法可以做到这一点,并且仍然有一个对象类型的参数

  case TypeCode.Int32:
    RunSignedVersion((int) o);
    break;
  case TypeCode.Int64:
    long n = (long) o;
    RunSignedVersion(n);
    break;

无法按int取消装箱的原因是,取消装箱和强制转换是两种不同的操作,它们恰好共享同一个运算符。

这是因为您只能取消装箱到最初装箱的同一类型(或该类型的可空版本)


例如,一个装箱的
字节
只能解装箱到
字节
字节
,一个装箱的
int
只能解装箱到
int
int
,一个装箱的
只能解装箱到
等。

解装箱操作只支持解装箱,不是你所期望的任何强迫

虽然这可能会令人沮丧,但值得注意的是,解决这一问题

  • 使拆箱成本大大提高
  • 由于方法重载选择上令人讨厌的边缘情况,可能会使语言复杂化
  • 其中,对于一些深入的解释,Eric Lippert一如既往

    如果您关心性能,唯一有效的方法就是(正如Jimmy指出的)

    这似乎不太繁重

    如果这太痛苦,那么您可以使用Convert.ToInt64或Convert.ToInt64()以及相关的成本

    void foo(object o)
    {
       switch (Type.GetTypeCode(o.GetType()))
       {
          case TypeCode.UInt32:
          case TypeCode.UInt64:
              ulong l = Convert.ToUInt64(o);
              RunUnsignedIntVersion(l);
              break;
          case TypeCode.Int32:
          case TypeCode.Int64:
              long n = Convert.ToInt64(o);
              RunSignedVersion(n);
              break;
       }
    }
    
    如果转换不可用,此处是相关方法的转子源:

        [CLSCompliant(false)]   
        public static ulong ToUInt64(object value) {
            return value == null? 0: ((IConvertible)value).ToUInt64(null);
        }
    
        [CLSCompliant(false)]   
        public static long ToInt64(object value) {
            return value == null? 0: ((IConvertible)value).ToInt64(null);
        }
    
    IConvertible在compact框架中作为一个接口受到支持,我认为这会因此起作用,但还没有尝试过

    如果您想要微框架,那么我建议您最好在每个类型的基础上实现转换选项。API就是说实际上没有太多其他的可能。我还建议,任何基于装箱的操作都是有风险的,因为在内存非常有限的环境中,这是一个巨大的分配开销


    如果您试图实现一个string.Format(),您是否考虑过后面跟一个ToString?

    您可以创建这样的扩展方法:

    public static class ConversionExtensions
    {
        public static ulong ToUInt64(this object value)
        {
            return ((IConvertible)value).ToUInt64();
        }
    }
    
    然后,您可以按如下方式使用它:

    object o = 123456U;
    ulong l = o.ToUInt64();
    

    我也这么想。有没有一种方法可以在不单独处理每种类型的情况下获得相同的结果?@ShuggyCoUk谢谢!不幸的是,转换类在.net micro中不可用。大约有11种数字类型需要特定的情况。没有一种简单的方法可以做到这一点,是吗?你可以创建自己的转换助手,然后使用它。@David Thibault。这实际上是字符串的帮助函数的一部分。格式:)我试图避免重新编写更多已存在于完整框架中的.net类。@ShuggyCoUk感谢IConvertible的更新。它可以在紧凑的框架中使用,但显然不能在Micro中使用。我只是将代码输入到编译器中,它无法解析IConvertible。谢谢你的巨大努力+1@ShuggyCoUk.NETMicro只提供了可在狭小空间(56Kb内存)中运行的基本功能。我们完全支持C#3.0编译器,但不支持需要泛型、linq、IConvertible和StringBuilder等库的功能。这显然是为了节省空间。因此,我们中的一些人能够负担额外的几kb,将不得不推出我们自己的StringBuilder,这是导致这个问题的最初原因。在这种特殊情况下,我将屏住呼吸,将原始的switch语句称为“解决方案”。请注意,当您开始考虑打开类型时,最好重新考虑您的设计。@RCIX我愿意接受建议。您还将如何使用诸如string.format()之类的通用输入实现某些东西?非常感谢大家花时间!
    object o = 123456U;
    ulong l = o.ToUInt64();