C#如何实现支持float与double的类A的类型安全Get返回方法
优化方案
方案1:改用泛型类(最高效、完全类型安全,优先推荐)
直接从类的定义层面约束存储的类型,从编译期就杜绝传错类型的可能,完全不需要运行时类型判断和dynamic转换:
// 泛型类定义,直接约束使用场景 public class A<T> { private readonly T _foo; // 构造函数类型校验,避免非法类型实例化 public A(T foo) { if (typeof(T) != typeof(float) && typeof(T) != typeof(double)) { throw new NotSupportedException("仅支持float和double类型"); } _foo = foo; } // 直接返回对应类型,无任何转换开销 public T GetFoo() { return _foo; } } // 用法示例 var floatA = new A<float>(1.23f); float f = floatA.GetFoo(); // 编译期直接确定返回类型,无错误可能 var doubleA = new A<double>(4.56d); double d = doubleA.GetFoo();
如果是.NET 7及以上版本,可以给泛型参数添加where T : INumber<T>约束,进一步在编译期过滤非数值类型,提升类型安全性。
方案2:保留非泛型类结构的优化方案
如果业务场景不允许修改为泛型类,可分两种情况优化:
子方案2.1 直接拆分类型明确的方法(零开销最优)
不需要强行使用泛型方法,直接定义对应类型的取值方法,完全编译期类型安全,无任何运行时开销:
public class A { private readonly float _fooV1; private readonly double _fooV2; public A(float foo) { _fooV1 = foo; } public A(double foo) { _fooV2 = foo; } public float GetFloat() => _fooV1; public double GetDouble() => _fooV2; }
子方案2.2 保留泛型方法的优化实现
如果必须保留泛型GetFoo<T>的接口定义,可针对原有问题做针对性优化:
- 移除dynamic,改用拆装箱转换,降低运行时开销
- 增加静态泛型缓存做类型预校验,避免每次调用重复判断类型
- 增加存储类型和请求类型的匹配校验,避免逻辑错误
public class A { private readonly object _foo; // 统一存储避免字段冗余 private readonly Type _valueType; public A(float foo) { _foo = foo; _valueType = typeof(float); } public A(double foo) { _foo = foo; _valueType = typeof(double); } public T GetFoo<T>() { // 静态泛型缓存:每种T只会执行一次类型校验 if (!GenericTypeCache<T>.IsSupported) { throw new ArgumentException($"不支持的类型{typeof(T).Name},仅支持float和double"); } // 校验请求类型和实际存储类型匹配 if (_valueType != typeof(T)) { throw new InvalidOperationException($"当前实例存储的是{_valueType.Name}类型,无法返回{typeof(T).Name}类型值"); } return (T)_foo; } // 静态泛型缓存类,每种T只会初始化一次 private static class GenericTypeCache<T> { public static readonly bool IsSupported = typeof(T) == typeof(float) || typeof(T) == typeof(double); } }
内容的提问来源于stack exchange,提问作者Julian A Avar C
相关产品推荐
相关产品推荐

