我正在使用IronRuby,并试图找出如何通过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#代码时,出现以下异常:


  参数数量错误(0代表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#示例的示例将需要将其包装在一个委托中(从字面上创建一个委托,该委托的调用会将参数传递给基础实例,然后将结果返回)。

有人可能会争辩说,如果这种翻译是自动的,那么翻译会更好,但是这样做会导致复杂而奇怪的边缘情况或错误,并且许多开发人员更愿意仅通过查看代码就知道会发生这种包装操作。在某些情况下,不一定总是会有合理的转换(或存在多个转换),因此让用户决定发生什么是明智的默认选择。

关于c# - 如何通过C#方法使用IronRuby块,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2288290/

10-13 03:16