如何在C#扩展方法中实现仅初始化一次的变量?
解决泛型扩展方法中变量仅初始化一次的问题
针对你的场景——扩展方法必须放在非泛型静态类中,但需要为每个泛型参数类型仅初始化一次对应的验证集合——可以通过泛型静态辅助类来实现,利用C#中泛型静态类的静态字段会按泛型参数独立实例化的特性。
核心方案
创建一个泛型静态辅助类,将需要仅初始化一次的泛型变量放在该类中。由于C#会为每个不同的泛型参数T创建独立的ValidatorHelper<T>实例,因此每个T对应的验证集合只会初始化一次。同时,扩展方法所在的类保持非泛型,满足语法要求。
代码实现
1. 泛型静态辅助类(存储仅初始化一次的变量)
// 泛型静态辅助类,每个T对应独立的静态成员 private static class ValidatorHelper<T> { // 用Lazy实现惰性初始化,第一次访问Value时才执行初始化逻辑 public static readonly Lazy<HashSet<T>> Scammers = new Lazy<HashSet<T>>(() => { // 这里替换为你的复杂源初始化逻辑,每个T仅执行一次 if (typeof(T) == typeof(long)) { // 针对long类型的诈骗号码初始化 return new HashSet<T>(new object[] { 2345678901L, 3456789012L, 4567890123L } as IEnumerable<T>); } // 其他类型的初始化逻辑(比如从数据库、配置文件加载) return LoadScammersFromSource<T>(); }); // 模拟从复杂源加载数据的方法 private static HashSet<T> LoadScammersFromSource<T>() { // 实际场景中替换为真实的加载逻辑 return new HashSet<T>(); } }
2. 非泛型静态类中的扩展方法
sealed class Caller // 无法修改的目标类 { public long Phone { get; set; } } // 扩展方法必须放在非泛型静态类中 static class Validator { // 泛型扩展方法,适用于任意类型T public static T Validate<T>(this T caller) where T : class { if (ValidatorHelper<T>.Scammers.Value.Contains(caller)) { throw new ArgumentException("已知诈骗者"); } return caller; } // 针对Caller类的重载(可选,更贴合原始场景) public static Caller Validate(this Caller caller) { if (ValidatorHelper<long>.Scammers.Value.Contains(caller.Phone)) { throw new ArgumentException("已知诈骗者"); } return caller; } }
关键说明
- 泛型静态类
ValidatorHelper<T>的静态成员会为每个不同的T单独创建实例,因此每个类型的验证集合只会初始化一次。 - 使用
Lazy<T>可以实现惰性初始化,只有当第一次需要使用验证集合时才执行加载逻辑,避免不必要的资源消耗。 - 扩展方法所在的
Validator类保持非泛型,完全符合C#对扩展方法的语法要求。
内容的提问来源于stack exchange,提问作者Rudiger W.
相关产品推荐
相关产品推荐

