c# - 泛型类型参数的 IEnumerable?
问题描述
我正在寻找一种方法来改进以下结构的代码:
foreach (var operation in operations)
{
if (IsTypeAndDoSomething<Type1>(operation))
{
Run((Type1)operation);
}
else if (IsTypeAndDoSomething<Type2>(operation))
{
Run((Type2)operation);
}
etc.
我宁愿避免一长串else if
具有基本相同模式的块。
在这个项目中,我们创建了一个重载的 Run 方法来执行每个操作。当一个操作列表正在运行时,我们需要首先确定每个操作的类型,然后准备它(DoSomething 部分),然后再使用Run
. 目前,如果方法似乎有必要,则重复 else 。
但是,我想知道 C# 中是否有任何方法可以使上面的代码更加“通用”而没有重复else if
的 s。
一个想法是创建一个类型的集合,例如
我想知道是否有任何方法可以将类型列表迭代为泛型类型参数?
var types = new[] {typeof(Type1), typeof(Type1)};
然后,当我们添加一个新的操作实现时,我们可以简单地将它添加到该集合中(而不是多个else if
块,我们将有另一个迭代器)。
但是,我们需要以某种方式将每个项目作为 Tx 传递:
IsTypeAndDoSomething<Tx>
似乎不可能在泛型类型参数 (T) 中引用这些类型。我认为这是因为它是在编译时而不是运行时完成的。
这是可能的还是推荐不同的模式?
解决方案
模式匹配的替代方法是使用访问者模式:
你介绍一个访问者界面
interface IOperationsVisitor<T> {
T Visit(Type1 obj);
T Visit(Type2 obj);
}
并为您的操作添加一个 Accept 方法到基类:
T Accept(IOperationsVisitor<T> visitor) => visitor.Visit(this);
然后,您只需实现访问者接口并Accept
在您的对象上调用该方法,并将访问者对象作为参数。
这比模式匹配要麻烦得多,但一个优点是,如果您引入新类型,您将被迫更新所有访问者以处理新类型。使用模式匹配很容易忘记检查类型的所有地方。
推荐阅读
- python - 如何遍历列表并创建子列表
- swift - 从 Firestore 数据库检索数据时出现问题
- php - 如何使用 php 在 html 表格中随机显示一行?
- javascript - 如何理解这个 Node 代码是如何工作的?
- python - 这个指针在这个 LinkedList 中指向哪个方向?
- node.js - 通过添加从另一个请求返回的身份验证令牌来修改 http 代理请求
- c++ - TerminateProcess 不适用于特定进程
- python-3.x - 创建二维数组
- javascript - 转换为 ISOString 后返回日期/时间而不切片的另一种方法?
- python - 为什么在 Python 的 csv.DictReader 中计算 csvfile 的行数会破坏我的代码?