本ブログは更新を停止しました。Aerieをよろしくお願いいたします。
投稿カレンダーはJavaScriptが有効でない環境では使用できません。
αετο? / aetos / あえとす
シャノン? 誰それ。
埼玉を馬鹿にする奴は俺が許さん。
基本的に知ったかぶり。興味を持った技術に手を出して、ちょっと齧りはするものの、それを応用して何か形にするまでは及ばずに飽きて放り出す人。
投稿日時 : 2008年1月17日 16:00
>拡張メソッドでなければ、即座に NullReferenceException が飛んで「ガッ」とやられるところですが これは callvirt でインスタンスメソッドを呼んだ場合,CLR がそのように振る舞うという話です. call でインスタンスメソッドを呼んだ場合,CLR は this が null かどうかをチェックしません.
ふーむ。 C# で call 命令を生成する方法はあるんですかね?
あ、VB.NET でもいいや。 C++/CLI は微妙。C++ はもともと、メンバ変数にアクセスしなければ大丈夫だし(規格上の保証は無いだろうけど)。
とりあえず以下のようなコードで this が null になります. using System; public class Foo { public string GetStr(int i) { Console.WriteLine("this is null? -> {0}", this == null); return i.ToString(); } } static class Program { static void Main(string[] args) { Func<Foo, int, string> f = Delegate.CreateDelegate( typeof(Func<Foo, int, string>), typeof(Foo).GetMethod("GetStr")) as Func<Foo, int, string>; Console.WriteLine(f(null, 1)); } } >C++ はもともと、メンバ変数にアクセスしなければ大丈夫だし 私の場合,.NET 言語を見るときは「生成された IL が動くかどうか」に興味があって,言語内で閉じた美しさとか完備性にはあまり興味がなかったりします. まあ Foo というクラスの int を引数にとって string を返すメソッドが, Func<Foo, int, string> にバインドできる CLR 型システムは,それなりに綺麗だとは思いますがね.
むー。 俺としては、呼び出し側の視点として、instance.Method(); と書くときの instance が null であってもよい、ということに対する驚きを書いてみたつもり。 呼び出される側にとっても this == null の場合があるというのは、(拡張メソッドである場合を除いては)驚きでもなんでもなく、むしろ迷惑というか。 # こういうサンプルを提示されることが迷惑、ではないです。 # GetStrにとって、こういう呼ばれ方をすることが迷惑、ということ。 まさか、そういう呼び方が可能であるから、あらゆるインスタンスメソッドは this == null である可能性を考慮しておけ、というわけでは当然無いだろうし。 > 私の場合,.NET 言語を見るときは「生成された IL が動くかどうか」に興味があって,言語内で閉じた美しさとか完備性にはあまり興味がなかったりします. 俺は正反対で、(今のところはまだ)言語にしか興味がありません。 それがどういう IL になってどう動くかは、敢えて意識しないようにしています。 だから Reflection.Emit なんか見たくもありません。 「インサイドIL 日本語版」とかいう本が出たら、一転して IL にどっぷりはまりそうな気もしますが。
>GetStrにとって、こういう呼ばれ方をすることが迷惑、ということ。 確かに迷惑ではありますが,必要な場所では NullReferenceException が発生するわけで,C/C++ の未初期化変数へのアクセスのような悪性の問題ではないと思っています. ちなみに,個人的な意見ですが,CLI が「this が this のように振る舞う」ということ自体を属性的に定義していなかったのは失敗だと思っています.this は元々特殊引数で,他のメソッド引数を this のように振る舞わせる仕組みは CLI には用意されていません. このため,拡張メソッドのように「this の様に見える第一引数」のセマンティクスと,従来の this のセマンティクスとが,微妙に異なってしまっています. 例えば値型に定義されたインスタンスメソッドを,拡張メソッドは再現できません.これは CLI 規格が,参照型と値型で this の扱いを変えるためです.拡張メソッドでは値型タイプの this の積み方をどうしても再現できません. ByRef を利用した拡張メソッドをサポートする VisualBasic はでは,さらにややこしくなります. VisualBasic では,C# でいうところの ref キーワードを書かないため, instance.Method() の instance が ref 渡しということが実際に可能です.そのため, instanceA.Swap( instanceB ) のようなコードも書けてしまいます. このあたりの問題については,以下の記事が詳しいです. http://blogs.msdn.com/vbteam/archive/2007/01/18/extension-methods-part-3.aspx http://blogs.msdn.com/sreekarc/archive/2007/04/25/extension-methods.aspx
詳しいことは良くわかりませんけど、 > 他のメソッド引数を this のように振る舞わせる仕組みは CLI には用意されていません. もしあったとしたら、C#にはなくてVBに用意される機能になりそうな気がします。なんとなく。
Powered by: Copyright © αετος / aetos