Hatena::Groupsubtech

ういはるかぜの化学

Tuesday, December 11, 2007

JScript.NET で型を指定しないとValueType(構造体)のプロパティやメソッドがうまく動かない 03:04  JScript.NET で型を指定しないとValueType(構造体)のプロパティやメソッドがうまく動かない - ういはるかぜの化学 を含むブックマーク はてなブックマーク -  JScript.NET で型を指定しないとValueType(構造体)のプロパティやメソッドがうまく動かない - ういはるかぜの化学

どうやら型指定なしだとJScriptEngineの変なObjectになるので、box化が働いてしまうためかプロパティセッターや内部の値をいじるようなメソッドが思った通りの挙動になりません。

例えば以下のコードを実行すると一見両方同じ結果になりそうですが実は違ってしまいます。

import System;
import System.Drawing;

var rect = new Rectangle(0, 0, 100, 100);
rect.X = 20;
Console.WriteLine(rect.X);

var rect2:Rectangle = new Rectangle(0, 0, 100, 100);
rect2.X = 20;
Console.WriteLine(rect2.X);

内部で何が起こっているのかはMSの人か、Roterのコードを読んだ人か、ildasmかReflectorで逆コンパイルした人にしかわからないのですが、このテストコードを逆コンパイルしてみると不思議オブジェクトを介していることが見て取れます。内部でオブジェクトごにょごにょしているときにValueTypeがbox化されてるんじゃないかと思われます。

Reflectorで逆コンパイルするとこんな感じです(空行は手でつけました)。

public object Global Code()
{
    Import.JScriptImport("System", base.engine);
    Import.JScriptImport("System.Drawing", base.engine);
    LateBinding binding = new LateBinding("X");
    LateBinding binding2 = new LateBinding("X");

    rect = new Rectangle(0x0, 0x0, 0x64, 0x64);
    binding.obj = Convert.ToObject(rect, base.engine);
    binding.SetValue(0x14);
    binding2.obj = Convert.ToObject(rect, base.engine);
    Console.WriteLine(binding2.GetNonMissingValue());

    rect2 = new Rectangle(0x0, 0x0, 0x64, 0x64);
    rect2.X = 0x14;
    Console.WriteLine(rect2.X);

    return null;
}

割と罠なので気をつけたほうがいい感じですが、JScript.NETなんて使わないですかそうですか。

トラックバック - http://subtech.g.hatena.ne.jp/mayuki/20071211