C#强类型枚举的入门理解

发布于:2025-05-15 ⋅ 阅读:(15) ⋅ 点赞:(0)

前言

在学习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> 的作用
    1. 从容器中筛选出所有符合 T 类型的实例。
    2. 返回 IEnumerable<T>,使调用方可以直接使用 T 类型的方法。
  • 适用场景
    • 依赖注入容器(如 QFramework 的 IOCContainer)。
    • 需要按类型动态查询对象的场景。

网站公告

今日签到

点亮在社区的每一天
去签到