Android 如何从上一个返回点恢复方法?
我想知道C#中是否存在某种机制,允许从上次调用过程中到达的最后一个返回“恢复”方法 我需要什么:我有一个抽象语法树(AST),它是由源语言设计的解析器创建的。这个抽象语法树是一个“根类”的对象,这个“根类”具有字段和其他类的实例等。我需要做的是创建一个sequencer,它接受这个抽象语法树,并通过生成器创建其他语言的指令。指令序列以null结尾。这可以通过生成器方法Android 如何从上一个返回点恢复方法?,android,c#,iterator,yield-return,Android,C#,Iterator,Yield Return,我想知道C#中是否存在某种机制,允许从上次调用过程中到达的最后一个返回“恢复”方法 我需要什么:我有一个抽象语法树(AST),它是由源语言设计的解析器创建的。这个抽象语法树是一个“根类”的对象,这个“根类”具有字段和其他类的实例等。我需要做的是创建一个sequencer,它接受这个抽象语法树,并通过生成器创建其他语言的指令。指令序列以null结尾。这可以通过生成器方法next()实现,该方法调用sequencer方法,动态计算下一条指令。换句话说,我不能浏览整个抽象语法树,生成所有指令并在每次调
next()
实现,该方法调用sequencer方法,动态计算下一条指令。换句话说,我不能浏览整个抽象语法树,生成所有指令并在每次调用next()
时逐个返回它们,但我必须在每次生成器调用next()时创建它们中的每一个
示例:我将发布一个伪代码,以便您更好地理解问题
static void Main(string[] args)
{Parser parser = new Parser (//constructor stuff);
Sequencer sequencer = new Sequencer(parser.Parse()); //the mehtod Parse() generates the AST
Generator generator = new Generator(sequencer);
Instruction instruction = generator.next();
while(instruction)
{print instruction
instruction = generator.next();
}
}
重要提示:我希望您理解的最重要的一点是,next()
并不总是在某种迭代中调用,因此我认为foreach
和迭代器不是一个好的解决方案。
这是因为为了使用iterotors,我终于要写一些
foreach(instruction in next())
{//do stuff with instruction}
我不想那样做
但是,我将让您了解应该如何构造next()
:
Instruction next()
{ return sequencer.generate();}
因此,generate()
:
最复杂的部分是,我需要一些具有收益率返回
行为的东西(因此从我在下一个generate()中离开的地方开始)
调用,但由于我前面解释的原因,没有使用迭代器。因此,在AST内部移动非常困难,因为我无法明确引用实际节点的父节点(如作为实际节点副本的字段)
由于这是不够的,您可以递归调用generate
(例如,如果有某种迭代构造函数需要翻译)
如何实现这一点?使用
yield return
实现主逻辑。这将创建一个枚举器。将其存储在类成员变量或其他永久性的地方
然后在返回普通对象的包装器方法中使用该枚举器,每次调用时从枚举器中提取一个新项。使用
产生返回
来实现主逻辑。这将创建一个枚举器。将其存储在类成员变量或其他永久性位置
然后在返回普通对象的包装器方法中使用该枚举器,在每次调用时从枚举器中提取一个新项。事实上,除了满足您的要求之外,还需要注意的是,它公开了该方法,这正是您在这里需要的
发电机:
public class Generator
{
//...
public IEnumerable<Instruction> Generate()
{
// ...
yield return new Instruction(...);
// ...
}
//...
}
我注意到可以在IEnumerable
上调用GetEnumerator
,这就回答了一个类似的问题
此外,正如中所指出的,您可以使用更准确地满足您需要的舒适方法包装MoveNext
和Current
。您甚至可以为IEnumerator
类型编写扩展方法:
public static class IEnumeratorExtensions
{
public static Instruction NextInstruction(this IEnumerator<Instruction> @this)
{
if (@this.MoveNext())
{
return @this.Current;
}
return null; // or throw, or whatever you like
}
}
公共静态类IEnumeratorExtensions
{
公共静态指令下一条指令(此IEnumerator@this)
{
如果(@this.MoveNext())
{
return@this.Current;
}
返回null;//或throw,或任何您喜欢的
}
}
事实上,除了满足您的需求之外,您还需要注意的是,它公开了方法,这正是您在这里需要的
发电机:
public class Generator
{
//...
public IEnumerable<Instruction> Generate()
{
// ...
yield return new Instruction(...);
// ...
}
//...
}
我注意到可以在IEnumerable
上调用GetEnumerator
,这就回答了一个类似的问题
此外,正如中所指出的,您可以使用更准确地满足您需要的舒适方法包装MoveNext
和Current
。您甚至可以为IEnumerator
类型编写扩展方法:
public static class IEnumeratorExtensions
{
public static Instruction NextInstruction(this IEnumerator<Instruction> @this)
{
if (@this.MoveNext())
{
return @this.Current;
}
return null; // or throw, or whatever you like
}
}
公共静态类IEnumeratorExtensions
{
公共静态指令下一条指令(此IEnumerator@this)
{
如果(@this.MoveNext())
{
return@this.Current;
}
返回null;//或throw,或任何您喜欢的
}
}
如果你告诉你想解决什么问题,答案很容易。这看起来像是一个。顺便说一句,你问的是状态机。你唯一想返回的问题是什么(没有);
而不是返回一些对象;
?我同意你的观点,但我不能发布整个“代码生成器”我应该发布抽象语法树类,可能还有语法分析器代码。显然,这是不可能的:DI编辑了整个问题,以便更好地理解问题及其约束。我希望它能帮助你(和我:P)@LovaJ.-我猜误解是因为您坚持认为IEnumerator.Current
/IEnumerator.MoveNext()
对绝对不如单个“next()”方法…如果您真的需要next())为什么不用一个方法来包装带有辅助类的C创建的迭代器?不知道为什么你认为“代码>前缀和<代码> iQueDebug <代码>作为一个单独的不可分离的概念……如果你告诉你要解决什么问题,这将是很容易回答的。这看起来像一个BTW。你所问的被称为状态机。是唯一的PR。你想放弃返回(无);
而不是放弃返回某个对象;
?我同意你的观点,但我不能发布