IronRuby と C#のバインディングを通じて、Azure上でホスティング出来ないか?を検討している。
その中でIronRuby と Hash構造について気になった事が出てきたのでまとめておく
.NET な環境で Hash構造
.NETな環境でも Ruby の Hashに近い構造があった。 「System.Collections.Generic.Dictionary ジェネリック クラス」である。
このクラスを元にIronRubyとの連携についてみてみる。
HttpRequestのHeaders プロパティ
何故、Dictionaryに興味が出たかというと、作業の関係上 HttpRequestのHeaders プロパティが出たからである。
結論から言うと、、HttpRequestのHeaders プロパティは System.Collections.Specialized.NameValueCollectionであり、Dictionaryではなかった。
このNameValueCollectionとIronRubyの事でハマったので記載する
検証コード
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Run2();
Console.ReadLine();
}
private static void Run2()
{
var engine = IronRuby.Ruby.CreateEngine();
var src = @"
puts '<<<c1>>>'
c1.each do |item|
puts item.class
puts item.inspect
end
puts '<<<c2>>>'
c2.each do |item|
puts item.class
puts item.inspect
end
";
var source = engine.CreateScriptSourceFromString(src);
var scope = engine.CreateScope();
var c1 = new System.Collections.Specialized.NameValueCollection();
c1.Add("abc", "123");
c1.Add("def", "234");
c1.Add("ghi", "456");
var c2 = new System.Collections.Generic.Dictionary<string, string>();
c2.Add("abc", "123");
c2.Add("def", "234");
c2.Add("ghi", "456");
scope.SetVariable("c1", c1);
scope.SetVariable("c2", c2);
source.Execute(scope);
}
}
}
NameValueCollection
このオブジェクトは System::String をキーとし、値も System::String である。 これを IronRubyから利用する場合には
var c1 = new System.Collections.Specialized.NameValueCollection();
c1.Add("abc", "123");
c1.Add("def", "234");
c1.Add("ghi", "456");
scope.SetVariable("c1", c1);
とした後
c1.each do |item| puts item.class puts item.inspect ## use item end
のようにした。
Ruby の Hash をご存知の方だと
hash.each do |key,val| ## use key and val end
としたいかと思うが、実際には違った。 Rubyの等価コードだと以下のように 思えるかと思う。
hash.keys.each do |key| ## use key end
Dictionary
このオブジェクトは System::String をキーとし、値も System::String である。 これを IronRubyから利用する場合には
var c2 = new System.Collections.Generic.Dictionary<string, string>();
c2.Add("abc", "123");
c2.Add("def", "234");
c2.Add("ghi", "456");
scope.SetVariable("c2", c2);
とした後
c2.each do |item| puts item.class puts item.inspect end
のようにした。
この結果
System::Collections::Generic::KeyValuePair[System::String, System::String] [abc, 123] System::Collections::Generic::KeyValuePair[System::String, System::String] [def, 234] System::Collections::Generic::KeyValuePair[System::String, System::String] [ghi, 456]
となり、Ruby の Hash のような感じがする。
これらの違い?
まだ詳しく調べていないが、「GetEnumerator メソッド」が影響していると 考えられる。
さいごに
当然のことながらRubyと.NET構造、よく似ているようで違う。 しかし ruby の each などが絶妙な形で融合している。 この点は興味深い。
皆さんもぜひ試していただけると(あまりいない)


コメントする