C# 数值类型的“基类”是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/828807/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:16:50  来源:igfitidea点击:

What is the "base class" for C# numeric value types?

c#types

提问by mike nelson

Say I want to have a method that takes any kind of number, is there a base class (or some other concept) that I can use?

假设我想要一个接受任何类型数字的方法,是否有我可以使用的基类(或其他一些概念)?

As far as I know I have to make overloads for all the different numeric types (Int32, Int16, Byte, UInt32, Double, Float, Decimal, etc). This seems awfully tedious. Either that or use the type "object" and throw exceptions if they are not convertable or assignable to a double - which is pretty bad as it means no compile time checking.

据我所知,我必须对所有不同的数字类型(Int32、Int16、Byte、UInt32、Double、Float、Decimal 等)进行重载。这看起来非常乏味。要么使用“对象”类型,如果它们不可转换或不可分配给双精度型,则抛出异常——这很糟糕,因为它意味着没有编译时检查。

UPDATE:OK thanks for the comments, you are right Scarecrow and Marc, in fact declaring it as Double actually works for all except Decimal.

更新:好的,谢谢你的评论,你是对的稻草人和马克,事实上,将它声明为 Double 实际上适用于除 Decimal 之外的所有对象。

So the answer I was looking for is Double - it acts like a base class here since most numeric types are assignable to it. (I guess Decimal is not assignable to Double, as it could get too big.)

所以我正在寻找的答案是 Double - 它在这里就像一个基类,因为大多数数字类型都可以分配给它。(我想 Decimal 不能分配给 Double,因为它可能会变得太大。)

public void TestFormatDollars() {
    int i = 5;
    string str = FormatDollars(i);   // this is OK
    byte b = 5;
    str = FormatDollars(b);     // this is OK
    decimal d = 5;
    str = FormatDollars(d);     // this does not compile - decimal is not assignable to double
}

public static string FormatDollars(double num) {
    return "$" + num;
}

采纳答案by mike nelson

The answer is: you don't need to provide overloads for ALL the numeric types, just for Doubleand Decimal. All others (except maybe some very unusually large ones) will be automatically converted to these.

答案是:您不需要为所有数字类型提供重载,只需要为DoubleDecimal提供重载。所有其他的(可能除了一些非常大的)将自动转换为这些。

Not a base classbut in fact that was the red herring. The base class System.ValueType doesn't help much as it includes types that are not numerics. The language reference i was reading was what got me confused in the first place :)

不是基类,但实际上那是红鲱鱼。基类 System.ValueType 没有多大帮助,因为它包含非数字类型。我正在阅读的语言参考首先让我感到困惑:)

(I was just looking for who to attribute the answer to and it was a combination of Scarecrow and Marc Gravell, but since they were comments i have put the answer here)

(我只是在寻找将答案归因于谁,它是稻草人和 Marc Gravell 的组合,但由于它们是评论,因此我将答案放在这里)

回答by Marc Gravell

There isn't one (or at least, not one that justmeans "numbers"). You could use:

没有一个(或者至少,没有一个仅仅意味着“数字”)。你可以使用:

void Foo<T>(T value) where T : struct {...}

But that allows anystruct - not just numbers. If you want to do arithmetic, generic operatorsmay be of use. Other than that; overloads it the most viable option.

但这允许任何结构 - 不仅仅是数字。如果您想进行算术运算,可能会用到泛型运算符。除此之外; 重载它是最可行的选择。

回答by LukeH

The base class of the numeric types is ValueType.

数字类型的基类是ValueType.

Unfortunately that still won't help you: DateTime, bool, Enumand hundreds of other types also derive from ValueType. There's no NumericTypebase class in .NET.

遗憾的是仍然不会帮助你:DateTimeboolEnum和数百个其他类型的也从中获得的ValueTypeNumericType.NET 中没有基类。

回答by Dmitrii Lobanov

The short answer is: Numeric types are value types, hence they derive from System.ValueType. The full answer is: you should read this article from MSDN. Moreover I think that you should read C# language reference :). Value type not equals numeric type, because values types include also structures and enumerations.

简短的回答是:数字类型是值类型,因此它们派生自 System.ValueType。完整的答案是:您应该阅读MSDN 上的这篇文章。此外,我认为您应该阅读 C# 语言参考 :)。值类型不等于数字类型,因为值类型还包括结构和枚举。

回答by Greg B

Are overloaded method signitures out of the question here? If you want a constrained group of methods to performe the same task you could voerload the public method and call a private method that takes any number via casting the input to a double.

重载的方法签名在这里是不可能的吗?如果您希望一组受约束的方法执行相同的任务,您可以加载公共方法并调用私有方法,该方法通过将输入转换为双精度数来获取任何数字。

回答by Luis

What I do:

我所做的:

 public interface INumeric<T>
 {
     T Zero { get; }
     T One { get; }
     T MaxValue { get; }
     T MinValue { get; }
     T Add(T a, T b);
     // T Substract(....
     // T Mult...
 }  

 public struct Numeric: 
     INumeric<int>, 
     INumeric<float>,
     INumeric<byte>,
     INumeric<decimal>,
     // INumeric<other types>
 {
     int INumeric<int>.Zero => 0;
     int INumeric<int>.One => 1;
     int INumeric<int>.MinValue => int.MinValue;
     int INumeric<int>.MaxValue => int.MaxValue;
     int INumeric<int>.Add(int x, int y) => x + y;

     // other implementations...
 }

Now, you can use it in a method:

现在,您可以在方法中使用它:

bool IsZero<TNum, T>(TNum ops, T number) 
   where TNum : INumeric<T>
{
   return number == ops.Zero;      
}

or extension method

或扩展方法

 public static bool IsZero<TNum, T>(this TNum ops, T number)
      where TNum : INumeric<T>
 {
      return number == ops.Zero;
 }

and in your code:

并在您的代码中:

 ...
 var n = new Numeric(); // can be an static prop

 Console.WriteLine(IsZero(n, 5)); // false
 Console.WriteLine(IsZero(n, 0f)); // true
 Console.WriteLine(IsZero(n, "0")); // compiler error

or, with extension method:

或者,使用扩展方法:

 Console.WriteLine(n.IsZero(5));  // false
 Console.WriteLine(n.IsZero(0f)); // true
 Console.WriteLine(n.IsZero("0")); // compiler error