如何使用C#方法使用IronRuby块

我正在使用Iron
Ruby并试图找出如何使用C#方法的块.

这是我试图模仿的基本Ruby代码:

def BlockTest ()
  result = yield("hello")
  puts result
end

BlockTest { |x| x + " world" }

我尝试用C#和IronRuby做同样的事情是:

 string scriptText = "csharp.BlockTest { |arg| arg + 'world'}\n";
 ScriptEngine scriptEngine = Ruby.CreateEngine();
 ScriptScope scriptScope = scriptEngine.CreateScope();
 scriptScope.SetVariable("csharp", new BlockTestClass());
 scriptEngine.Execute(scriptText, scriptScope);

BlockTestClass是:

public class BlockTestClass
{
    public void BlockTest(Func<string, string> block)
    {
        Console.WriteLine(block("hello "));
    }
}

当我运行C#代码时,我得到一个例外:

wrong number of arguments (0 for 1)

如果我将IronRuby脚本更改为以下内容,则可以正常工作.

 string scriptText = "csharp.BlockTest lambda { |arg| arg + 'world'}\n";

但是如何让它与原始的IronRuby脚本一起使用,以便它等同于我原来的Ruby示例?

 string scriptText = "csharp.BlockTest { |arg| arg + 'world'}\n";

最佳答案 Ruby的块不是c#(或任何其他.Net语言)理解的概念.

要在委托的c#中“传递一个”相似的概念,你必须将它“包装”在可理解的东西中.

通过从块中创建一个lambda,它可以转换为c#代码,期望委托或表达式.

这是’Alt.Net’社区的一个常见问题,即使对于像f#这样的祝福语言,其中’函数指针’没有实现为委托,而是略有不同(例如f#中的FastFunc实例)将其中一个传递给类似你的c#例子需要将它包装在一个委托中(字面上创建一个委托,其调用将参数传递给底层实例并返回结果).

有人可能会争辩说,如果它是自动的,这样的翻译会更好,但这样做会导致复杂和奇怪的边缘情况或错误,许多开发人员更愿意知道只需查看代码就会发生这样的包装操作.情况也可能并非总是存在合理的转换(或存在多个转换),因此让用户决定发生的是合理的默认值.

点赞