How to use an IronRuby block with a C# method

白昼怎懂夜的黑 提交于 2019-12-05 14:01:27

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.

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.

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!