给出一个MethodBase
或MethodInfo
实例,如何检查它代表的是迭代器方法(带有yield
语句)还是普通方法(没有yield
语句) ?
我注意到IteratorStateMachineAttribute
属性中有一个CustomAttributes
,但是here提到应该不依赖此属性。
答案 0 :(得分:0)
否,这是不可能的-由于yield
是编译器在编译过程中正在处理的上下文关键字,因此您无法直接对其进行检查(请参阅yield contectual keyword)-您可以找到{{ 3}}是C#语言提供的连续关键字的列表。
定义
上下文关键字(例如
yield
)用于在代码中提供特定的含义,但在C#中不是保留字。某些上下文关键字,例如partial
和where
,在两个或多个上下文中具有特殊含义。
您可以找到类似的解释here,为什么不能通过反射轻松找到它。
但是我认为检查IEnumerable
就足够了-因为此接口保证了Iterator可用(请参见here)。请考虑以下方法:
IEnumerable<int> Iterator()
{
for (int i = 0; i < 10; i++)
{
yield return i;
};
}
一种检查是否可以进行迭代的方法是:
if (Iterator() is IEnumerable)
foreach (var item in Iterator())
{
Debug.WriteLine(item.ToString());
}
else
Debug.WriteLine("Cannot iterate!");
另一种方法是通过泛型进行声明:
void Iterate<T>(T iterator)
where T: System.Collections.IEnumerable
{
foreach (var item in iterator)
{
Debug.WriteLine(item.ToString());
}
}
您可以通过以下方式调用它:
Iterate(Iterator());
区别在于,通过泛型,编译器将在应用程序运行之前 对其进行检查并给出编译错误,而第一个示例在运行时 对其进行检查,即它将编译但在运行时失败。
当然,您也可以遍历数组,这很好用(请参见下面由iterators添加的注释):
var intArray = new int[] {1,2,3};
Iterate(intArray);
您还可以显式检查枚举数,即
void Iterate2<T>(T collection)
where T: IEnumerable
{
var enumerator = collection.GetEnumerator();
if (enumerator is IEnumerator)
while (enumerator.MoveNext())
{
var item = enumerator.Current;
Console.WriteLine(item.ToString());
}
}
我把这些例子放在一起 CodeCaster 因此您可以立即尝试。