浮点数的通用扩展方法?



在。net 7中,有IFloatingPoint。我阅读了。net 6的以下代码。它使用struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>。所有这些约束都是必要的吗?

代码:

using System;
namespace MyExtensions
{
public static class NumericExtensions
{
public static T Round<T>(this T value, int decimalPlaces) where T : 
struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
{
decimal decimalValue = Convert.ToDecimal(value);
decimal rounded = Math.Round(decimalValue, decimalPlaces);
return (T)Convert.ChangeType(rounded, typeof(T));
}
}
}

舍入只对浮点数有意义。在c#中,我们只有三种类型的浮点数(float,double,decimal)。Math.Round方法有两个变体,一个用于double,一个用于decimal。两者在内部使用不同的舍入算法。对小数的双精度使用舍入方法,反之亦然,都可能导致意想不到的结果。

由于我们只有三个相关的类型,生成扩展方法的最简单方法是为每个类型编写一个扩展方法。每个类型一行就足够了:

public static class NumericExtensions
{
public static double Round(this double value, int decimalPlaces) => Math.Round(value, decimalPlaces);
public static decimal Round(this decimal value, int decimalPlaces) => Math.Round(value, decimalPlaces);
public static float Round(this float value, int decimalPlaces) => (float)Math.Round(value, decimalPlaces);
}

从。net 7开始,框架中的数字类型被扩展为实现泛型接口,这使得编写处理数字的泛型方法变得更加容易。现在浮点类型本身也有Round()方法,所以我们不必再使用Math.Round(),而是可以使用实际类型的Round()方法。

有了这个新的支持,我们可以编写一个支持所有浮点类型(也包括新的Half类型)的扩展方法:
public static class NumericExtensions
{
public static T Round<T>(this T value, int decimalPlaces) where T : IFloatingPoint<T> => T.Round(value, decimalPlaces);
}

  • 微软博客文章关于。net 7中数字类型的新泛型能力

最新更新