求助:如何实现支持数值类型的泛型Average<T>类
解决泛型Average数值类型约束的问题
我明白你卡在这里一整天有多头疼——你之前的思路问题出在:int并没有继承你定义的NumericBase<int>,所以Average<int>根本满足不了where T:NumericBase<T>的约束,自然没法按预期使用。下面给你两种可行的解决方案,分别适配不同的.NET版本:
方案1:.NET 7及以上(推荐,最简洁)
.NET 7引入了System.Numerics.INumber<T>接口,它为所有数值类型(int、float、double等)提供了统一的数值运算能力,完美解决你的需求:
using System.Numerics; public class Average<T> where T : INumber<T> { private T _sum = T.Zero; private int _count = 0; // 向实例添加元素 public void Add(T item) { _sum += item; _count++; } // 计算平均值 public T Average() { if (_count == 0) throw new InvalidOperationException("无法计算空集合的平均值,请先添加元素。"); // 将计数转换为T类型,确保除法运算类型匹配 return _sum / T.CreateChecked(_count); } // 重置实例状态 public void Reset() { _sum = T.Zero; _count = 0; } }
使用方式完全符合你的预期:
Average<int> av = new Average<int>(); av.Add(3); av.Add(4); int averageValue = av.Average(); // 结果为3(int整数除法特性) av.Reset(); // 也支持float等其他数值类型 Average<float> floatAv = new Average<float>(); floatAv.Add(3.5f); floatAv.Add(4.5f); float floatAvg = floatAv.Average(); // 结果为4.0f
方案2:兼容.NET Framework/.NET 6及以下
如果你的项目无法升级到.NET 7,可以自定义一个数值运算接口,为每个需要支持的数值类型实现该接口,再通过隐式转换让使用更顺畅:
第一步:定义数值运算接口
public interface INumeric<T> { // 加法运算 T Add(T other); // 除以整数的运算 T Divide(int divisor); // 获取该类型的零值 static abstract T Zero { get; } }
第二步:为int实现接口(以int为例,其他类型类似)
public struct NumericInt : INumeric<int> { private readonly int _value; public NumericInt(int value) => _value = value; public int Add(int other) => _value + other; public int Divide(int divisor) => _value / divisor; public static int Zero => 0; // 隐式转换,允许直接传入int类型值 public static implicit operator NumericInt(int value) => new NumericInt(value); // 隐式转换,允许直接将结果转为int public static implicit operator int(NumericInt numeric) => numeric._value; }
第三步:实现泛型Average类
public class Average<T> where T : INumeric<T> { private T _sum = INumeric<T>.Zero; private int _count = 0; public void Add(T item) { _sum = _sum.Add(item); _count++; } public T Average() { if (_count == 0) throw new InvalidOperationException("无法计算空集合的平均值,请先添加元素。"); return _sum.Divide(_count); } public void Reset() { _sum = INumeric<T>.Zero; _count = 0; } }
使用示例:
Average<NumericInt> av = new Average<NumericInt>(); av.Add(3); // 隐式转换为NumericInt av.Add(4); int averageValue = av.Average(); // 隐式转换回int av.Reset();
你只需要为需要支持的数值类型(比如float、double、byte)都实现INumeric<T>接口,就能复用这个Average类了。
内容的提问来源于stack exchange,提问作者Dmitry L
相关产品推荐
相关产品推荐

