C#强类型枚举的入门理解
前言
在学习QFramework框架底层逻辑时,发现有两处代码不理解:
mArchitecture.mContainer.GetInstancesByType<IModel>().Where(m => !m.Initialized)
public IEnumerable<T> GetInstancesByType<T>()
{var type = typeof(T);return mInstances.Values.Where(instance => type.IsInstanceOfType(instance)).Cast<T>();
}
此处用到C#强类型枚举(Strongly Typed Enumeration)相关知识。
强类型枚举的含义
在 C# 中,强类型枚举并不是一个官方的术语,但它通常用来描述 通过泛型约束或类型转换,确保集合中的元素具有明确的类型,而不是笼统的 object
或动态类型。
.Cast<T>()
的作用
在 GetInstancesByType<T>
方法中,.Cast<T>()
的作用就是将筛选出的 object
实例转换为具体的类型 T
,从而返回一个 类型安全的集合(IEnumerable<T>
)。
为什么需要强类型枚举?
1)弱类型的缺陷
假设有一个非泛型的容器,存储的是 object
类型:
List<object> instances = new List<object> { new PlayerModel(), new EnemyModel() };
当你从 instances
中取出元素时,默认是 object
类型:
var model = instances[0]; // 类型是 object,无法直接调用 PlayerModel 的方法
必须手动强制转换:
var player = (PlayerModel)instances[0]; // 不安全,可能抛出 InvalidCastException
2)避免弱类型缺陷的解决方案
通过 Cast<T>()
或 OfType<T>()
,可以直接获取 T
类型的集合:
IEnumerable<IModel> models = instances.Cast<IModel>(); // 所有元素都是 IModel 类型
- 优势:
- 编译时类型检查,避免运行时转换错误。
- 可以直接调用
T
类型的方法,无需额外转换。
那么
GetInstancesByType<T>
是如何实现强类型枚举的呢?
public IEnumerable<T> GetInstancesByType<T>()
{var type = typeof(T);return mInstances.Values.Where(instance => type.IsInstanceOfType(instance)) // 筛选符合 T 类型的实例.Cast<T>(); // 转换为 IEnumerable<T>
}
Where
筛选:确保所有元素都符合T
类型(如IModel
)。Cast<T>
转换:将object
转换为T
,使返回的集合可以直接使用T
的方法。
示例代码
###假设 `mInstances` 存储了以下对象:
mInstances = {{ typeof(PlayerModel), new PlayerModel() },{ typeof(EnemyModel), new EnemyModel() },{ typeof(InputSystem), new InputSystem() }
}###调用 `GetInstancesByType<IModel>()`:
##1. 筛选出所有 `IModel` 实例(`PlayerModel` 和 `EnemyModel`)。
##2. 使用 `Cast<IModel>()` 返回 `IEnumerable<IModel>`:
IEnumerable<IModel> models = GetInstancesByType<IModel>();
foreach (var model in models)
{model.Init(); // 可以直接调用 IModel 的方法
}
Cast<T>()比对OfType<T>()
方法 | 行为 | 是否抛出异常 |
---|---|---|
Cast<T>() | 强制转换,要求所有元素必须是 T 类型 | 如果元素不是 T 类型,抛出 InvalidCastException |
OfType<T>() | 安全筛选,只返回符合 T 类型的元素 | 不会抛出异常,不符合的元素会被忽略 |
在 GetInstancesByType<T>
中:
- 由于已经用
Where
确保所有元素符合T
类型,所以Cast<T>
是安全的。 - 如果担心潜在的类型问题,可以用
OfType<T>
替代:
return mInstances.Values.OfType<T>();
总结
- 强类型枚举:通过泛型或
Cast<T>/OfType<T>
,让集合的元素具有明确的类型,避免手动转换。 GetInstancesByType<T>
的作用:- 从容器中筛选出所有符合
T
类型的实例。 - 返回
IEnumerable<T>
,使调用方可以直接使用T
类型的方法。
- 从容器中筛选出所有符合
- 适用场景:
- 依赖注入容器(如 QFramework 的
IOCContainer
)。 - 需要按类型动态查询对象的场景。
- 依赖注入容器(如 QFramework 的