我在我试图派生的类上做了一个Go To Definition( F12 ),我注意到其中一个方法标有AsyncStateMachineAttribute
。而这又继承了StateMachineAttribute
。我很好奇并决定在MSDN上阅读这个属性及其所有衍生物。这导致我this,我发现了这句话:
您不能使用
IteratorStateMachineAttribute
来测试方法是否是C#中的迭代器方法。
因为这个陈述是突出的,所以必须有严重的含义,但没有进一步解释为什么会这样。有没有人有这方面的见解?
答案 0 :(得分:8)
我99%肯定它的历史。基本上,C#在引入此属性之前在C#2中引入了迭代器块 - long 时间。
等效的异步属性与C#中的异步方法同时引入,所以很好......但即使C#编译器现在将IteratorStateMachineAttribute
应用于迭代器块:
我会说方法上存在IteratorStateMachineAttribute
是一个很好的指标,它 是一个迭代器方法(虽然没有什么可以阻止恶作剧的开发人员申请它适用于其他方法),但由于旧版本的C#编译器,它并不是一个充分的测试。
答案 1 :(得分:3)
这里的状态机是由C#编译器自动生成的。在继续之前,C#编译器在内部将许多高级功能(如闭包,yield关键字和async)转换为简化的C#。像'AsyncStateMachineAttribute'之类的东西就是这样的事情发生的一点证据。您可能也熟悉所调用的类,例如DisplayClass923084923'1,它们是C#生成的用于实现闭包的类。
当你使用'yield'时,比如说,C#编译器首先生成一个不使用'yield'但是使用状态机实现的代码版本。原则上,从此;
yield "A";
yield "B";
到
int _state = 0;
if (_state == 0) { state = 1; return "A"; }
if (_state == 1) { state = 2; return "B"; }
这意味着后来的C#编译器不必处理'yield'本身 - 它已被简化为整数和返回语句。我认为这是添加IteratorStateMachineAttribute
的地方 - 对于类的简化,整理和返回版本。
(我认为Async以相同的方式工作,生成一个简化的状态机作为其简化步骤,这就是你在文档中提到它的方式。)
但是,从最早的C#版本开始,您就拥有foreach
关键字,该关键字适用于任何具有GetEnumerator
方法的对象,并且该枚举器具有MoveNext
等方法}和Result
。
所以 - 迭代器方法可能以不同的方式产生。 IteratorStateMachineAttribute
是编译器在某些情况下提供的,但你不应该依赖它在那里。
答案 2 :(得分:0)
这告诉您不能将此标志应用于方法,因为在编译期间它会注入一些无法可靠地添加到方法的IL代码。