为什么c#中没有基数类型的数字?

时间:2009-09-13 17:01:29

标签: c# .net

与java不同,为什么c#没有浮点数,整数等的超类型?在c#中避免使用Number的任何理由?

6 个答案:

答案 0 :(得分:6)

因为无法继承值类型。

答案 1 :(得分:4)

我不知道是否属实,但我听到的一个解释是权重 - 特别是对于小框架(Compact Framework,Silverlight,Micro Framework);我不相信......

更有说服力的是本身知道它是一个数字并不能提供太多;例如,整数除法与浮点的工作方式非常不同,运算符并不总是如你所愿那么简单(想想DateTime + TimeSpan => DateTimeDateTime - DateTime => TimeSpan)。

如果有帮助,MiscUtil提供generic operator support,允许这样的内容:

T x = ..., y = ...; // any T that has suitable operators
T sum = Operator.Add(x,y);

一切都非常干净,高效。但请注意,没有编译时验证(因为没有合适的通用约束)。但它确实有效。

答案 2 :(得分:3)

它可能有性能原因 - 数字,struct - 类型,是堆栈分配和快速但不允许继承结构。以OO方式使用它们需要非常大量的自动/拆箱,并且由于大量更多内存消耗 vtable lookup 来解决多态性,因此需要大幅降低性能

Java已经引入了面向对象的包装器,并且最终会出现不同且不兼容的实现,因为它们更加奇怪。

为数字提供快速抽象的更好的可能性是在Haskell或C ++中引入类型类 /概念,您可以在其中编写:

sum :: (Num t) => [t] -> t

读为 Sum获取类型t的元素列表 - 其中t是数字类型 - 并返回这样的数字。可以在编译时优化此机制,而不会产生任何性能开销。但.NET和Java都没有这样的技术。

答案 3 :(得分:1)

但非常有用,如果他们已经包含它,那么已经定义了所有整数数字类型(int,short,long,uint等)来实现一个名为IIntegral的空接口,并且所有数字类型(Integral plus decimal,float等)都已定义为实现名为INumeric的空接口。

这将允许泛型具有基于这些接口的指定约束,以将允许类型限制为整数类型或数字类型,这是目前更难解决的问题。

答案 4 :(得分:1)

ValueType非常接近。没有多少值类型无法表示为单个数字:

  static void Main(string[] args)
  {
     int myInteger = 42;
     decimal myDecimal = 3.141592653589793238M;
     long myLong = 900000000000;
     byte myByte = 128;
     float myFloat = 2.71828F;

     TestFunction(myInteger);
     TestFunction(myDecimal);
     TestFunction(myLong);
     TestFunction(myByte);
     TestFunction(myFloat);
  }

  static void TestFunction(System.ValueType number)
  {
     Console.WriteLine(number.ToString());
  }

输出:

  • 42
  • 3.141592653589793238
  • 9000亿
  • 128
  • 2.71828

答案 5 :(得分:0)

您可以为Object创建一个扩展名,为您返回一个bool,就像这样(未经测试,可能会提供误报等)(捕获小数,浮点数,整数,使用美国样式的十进制分隔符;修改正则表达式以适合十六进制等等。)

public static class Object
{
    static Regex r = new Regex(@"^\d*\.*\d$", RegexOptions.Compiled);
    public static bool IsNumber(this object obj)
    {
        return r.IsMatch(obj.ToString() && !(obj is string);
    }
}

因为ToString是Object的一部分,所有东西最终都是对象的孩子......

当然,这不会提供类型安全或泛型或类似的东西,但它仍然会让你做更多的工作类似的事情。您没有指定您想要基类的内容,是否要在任何地方接受任何数字类型作为参数,或者您想要泛型。这可能会让你在任何地方都可以到达。

用法:

public class thingThatHasNumericValue
{
    private object arbNumber;
    public object SomeArbitraryNumber
    {
        get { return arbNumber; }
        set
        {
            if (!arbNumber.IsNumber())
            {
                throw new InvalidOperationException("Must be a number");
            }
            arbNumber = value;
        }
    }
}