2

私はIronRubyを使用していて、ブロックをC#に渡すためのシームレスな方法を考え出そうとしています。この質問は、 C#でIronRubyブロックを使用する方法の続きであり、IronRubyとC#の間でブロックを渡すことができないことを示しています。

私の次の質問は、Rubyラッパーメソッドを使用してブロックをラムダまたはProcオブジェクトにし、それをC#に渡す方法で同じ目標を達成する方法があるかどうかについてです。

私がやりたいことの線に沿ったいくつかのコードを以下に示します。コードは機能しませんが、意図が十分に明確であることを願っています。

string scriptText =
    @"def BlockTest
     result = csharp.BlockTest somehow-pass-the-block ("hello")
     puts result
    end
    BlockTest { |arg| arg + 'world'}";

Console.WriteLine("Compiling IronRuby script.");
ScriptEngine scriptEngine = Ruby.CreateEngine();
ScriptScope scriptScope = scriptEngine.CreateScope();
scriptScope.SetVariable("csharp", new BlockTestClass());
scriptEngine.Execute(scriptText, scriptScope);

C#BlockTestクラスは次のとおりです。

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

3 に答える 3

2

ブロックは、CLR には実際には存在しない不思議なものです。ただし、Ruby にはproc、CLR デリゲートに類似した があります。

たとえば、これはうまくいくはずです:

C#:

public class SomeClass {
    public static void Run(Func<int, int> func) { ... }
}

ルビー:

proc = lambda { |i| i + 10 }
SomeClass.Run(proc)

新しい proc を作成するにはいくつかの方法があります (多くの人は を好みますProc.newが、C# 関数と同じようには機能しないため、ラムダを好みます)、重要なポイントは次のとおりです。

lambda(およびProc.new) は関数です。関数にブロックを渡すと、ブロックProcをラップする新しいオブジェクトが生成されます。

を使用して、ブロックが関数に渡されるときに暗黙的にブロックをプロシージャに変換する方法もあります&

ルビー:

def each
  yield 1
end

と同じです

def each(&block)
  block.call 1
end

&、メソッドに渡されたブロック (それ以外の場合は によって暗黙的に呼び出されるyield) を受け取り、それを に変換しProcます。プロシージャになったら、それを渡したり、配列に貼り付けたり、C# に渡したりできます。

したがって、C# メソッドを呼び出すには、次の 2 つのオプションがあります。

  1. &ブロックを受け取り、それを使用して proc に変換するラッパー メソッドを作成します。その後、このプロシージャを使用して基になる C# メソッドを呼び出すことができます

  2. lambdaorを使用Proc.newして ruby​​ で直接 proc を作成し、C# メソッドに渡します。

例:

C# コード (共通):

public static class MyClass
{
    public static void Print(Func<int, int> converter)
    {
        Console.WriteLine("1: {0}", converter(1));
    }
}

Ruby コード 1 (ラッパー):

class MyClass
  class << self # this is only needed to alias class (static) methods, not for instance methods
    alias_method :original_print, :print
  end

  def self.print(&block)
    original_print block
  end
end

MyClass.print {|i| i * 10}

Ruby コード 2 (直接):

MyClass.print lambda{|i| i * 10}
于 2010-02-28T19:36:15.850 に答える
0

完全な答えはわかりませんがblock.to_proc、呼び出して呼び出し可能なProcオブジェクトに変換すると、さらに遠くに到達する可能性があります。

于 2010-02-19T00:31:14.393 に答える
0

Func<>-Delegates と Blocks または Procs では成功しませんでした。Proc怠惰に、私は C# で -Classを使用し、 Ruby から で呼び出しましたblock.to_proc。C# ではProc.Call、結果を使用してキャストできます。

かなり時間が経っているので、これは時代遅れかもしれません。

于 2010-02-23T15:25:31.803 に答える