与java不同,为什么c#没有浮点数,整数等的超类型?在c#中避免使用Number的任何理由?
答案 0 :(得分:6)
因为无法继承值类型。
答案 1 :(得分:4)
我不知道是否属实,但我听到的一个解释是权重 - 特别是对于小框架(Compact Framework,Silverlight,Micro Framework);我不相信......
更有说服力的是本身知道它是一个数字并不能提供太多;例如,整数除法与浮点的工作方式非常不同,运算符并不总是如你所愿那么简单(想想DateTime + TimeSpan => DateTime
,DateTime - 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());
}
输出:
答案 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;
}
}
}