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

发布于 2024-08-22 05:01:50 字数 1096 浏览 7 评论 0原文

我正在使用 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";

I'm using IronRuby and trying to work out how to use a block with a C# method.

This is the basic Ruby code I'm attempting to emulate:

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

BlockTest { |x| x + " world" }

My attempt to do the same thing with C# and IronRuby is:

 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);

The BlockTestClass is:

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

When I run the C# code I get an exception of:

wrong number of arguments (0 for 1)

If I change the IronRuby script to the following it works.

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

But how do I get it to work with the original IronRuby script so that it's the equivalent of my original Ruby example?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

难得心□动 2024-08-29 05:01:50

Ruby 的块不是 C#(或任何其他 .Net 语言)理解的概念。

要“传递一个”到委托的 C# 中的类似概念,您必须将其“包装”在可以理解的内容中。

通过从块中创建 lambda,您可以将其传递给需要委托或表达式的 C# 代码。

这是“Alt.Net”社区的一个常见问题,即使是像 f# 这样的受祝福的语言,其中“函数指针”不是作为委托实现的,而是以稍微不同的方式(例如 f# 中的 FastFunc 实例)将其中一个传递给像您的 c# 示例之类的东西需要将其包装在委托中(实际上创建一个委托,其调用将参数传递给底层实例并返回结果)。

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

Ruby's blocks are not a concept understood by c# (or any of the other .Net languages).

To 'pass one' to the similar concept in c# of the delegate you must 'wrap it' in something that is understandable.

By making a lambda out of the block it becomes something you can pass to c# code expecting a delegate or expression.

This is a common issue with the 'Alt.Net' community, even for blessed languages like f# where 'functions pointers' are not implemented as delegates but instead are done slightly differently (FastFunc instances in f# for example) to pass one of these to something like your c# example would require wrapping it in a delegate (literally creating a delegate whose invocation passes the parameters to the underlying instance and returns the result back).

One could argue that such translation would be nicer if it was automatic, but doing that can lead to complex and strange edge cases or bugs and many developers prefer to know that such a wrapping operation will occurred just by looking at the code. It is also the case that there may not always be reasonable conversion (or more than one exists) so making the user decide what happens is a sensible default.

橘寄 2024-08-29 05:01:50

在大多数情况下,IronRuby Procs 和 lambda 可以与 CLR Actions、Funcs、委托类型和动态对象互换。然而,除了一些调用站点转换之外,几乎没有 Ruby 语法糖。一旦我们确实优化了 .NET 事件的语法; IronRuby 允许将 Ruby 块作为 CLR 事件处理程序传递:button.on_click {|s,e| ... }

我们尝试了很多方法来允许将块传递给 CLR 方法;通过检测最后一个参数是可调用对象的方法,或者通过允许特殊的命名参数。已经为此开放了一个功能请求(尽管名称很神秘):http://ironruby.codeplex.com/workitem /4511。对于任何愿意做出贡献的人来说,这将是一个很好的挑战。

For the most part, IronRuby Procs and lambdas are interchangeable with CLR Actions, Funcs, delegate types, and dynamic objects. However there's little Ruby syntactic sugar over this, other than some call-site conversions. Once place we did sweeten up the syntax was for .NET events; IronRuby allows passing a Ruby block as an CLR event handler: button.on_click {|s,e| ... }.

We have toyed a bunch of ways to allow blocks to be passed to CLR methods; either by detecting methods whose last argument is a callable object, or by allowing a special named parameter. There's a feature request (though cryptically named) already open for this: http://ironruby.codeplex.com/workitem/4511. Would be a good challenge for anyone willing to contribute.

流年已逝 2024-08-29 05:01:50

您完全可以在 C# 中使用 ruby​​ 块,事实上我已经在当前正在生产的应用程序中使用了它!方法如下:

在 c# 文件中:

public void BlockTest(dynamic block)
{
Console.WriteLine(block.call("world"));
}

在 Ironruby 中:

#require the assembly
block = Proc.new {|i| "hello " + i }
Blah::Blah.BlockTest block

注意:仅在 c# 4.0 中测试

You can totally use ruby blocks in c#, in fact i have used this in an application that is currently in production! here is how:

In c# file:

public void BlockTest(dynamic block)
{
Console.WriteLine(block.call("world"));
}

In Ironruby:

#require the assembly
block = Proc.new {|i| "hello " + i }
Blah::Blah.BlockTest block

note: tested in c# 4.0 only

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文