東方算程譚

Oriental Code Talk ── επιστημηが与太をこく、弾幕とは無縁のシロモノ。

目次

Blog 利用状況

ニュース

著作とお薦めの品々は

著作とお薦めの品々は
東方熱帯林へ。

あわせて読みたい

わんくま

  1. 東京勉強会#2
    C++/CLI カクテル・レシピ
  2. 東京勉強会#3
    template vs. generics
  3. 大阪勉強会#6
    C++むかしばなし
  4. 東京勉強会#7
    C++むかしばなし
  5. 東京勉強会#8
    STL/CLRによるGeneric Programming
  6. TechEd 2007 @YOKOHAMA
    C++・C++/CLI・C# 適材適所
  7. 東京勉強会#14
    Making of BOF
  8. 東京勉強会#15
    状態遷移
  9. 名古屋勉強会#2
    WinUnit - お気楽お手軽UnitTest

CodeZine

  1. Cで実現する「ぷちオブジェクト指向」
  2. CUnitによるテスト駆動開発
  3. SQLiteで組み込みDB体験(2007年版)
  4. C++/CLIによるCライブラリの.NET化
  5. C# 1.1からC# 3.0まで~言語仕様の進化
  6. BoostでC++0xのライブラリ「TR1」を先取りしよう (1)
  7. BoostでC++0xのライブラリ「TR1」を先取りしよう (2)
  8. BoostでC++0xのライブラリ「TR1」を先取りしよう (3)
  9. BoostでC++0xのライブラリ「TR1」を先取りしよう (4)
  10. BoostでC++0xのライブラリ「TR1」を先取りしよう (5)
  11. C/C++に対応した、もうひとつのUnitTestFramework ─ WinUnit
  12. SQLiteで"おこづかいちょう"
  13. STL/CLRツアーガイド
  14. マージ・ソート : 巨大データのソート法
  15. ヒープソートのアルゴリズム
  16. C++0xの新機能「ラムダ式」を次期Visual Studioでいち早く試す
  17. .NETでマンデルブロ集合を描く
  18. .NETでマンデルブロ集合を描く(後日談)
  19. C++/CLI : とある文字列の相互変換(コンバージョン)
  20. インテルTBBによる選択ソートの高速化
  21. インテルTBB3.0 によるパイプライン処理
  22. Visual C++ 2010に追加されたSTLアルゴリズム
  23. Visual C++ 2010に追加されたSTLコンテナ「forward_list」
  24. shared_ptrによるObserverパターンの実装
  25. .NETでマンデルブロ集合を描く(番外編) ── OpenCLで超並列コンピューティング
  26. StateパターンでCSVを読む
  27. 状態遷移表からStateパターンを自動生成する
  28. 「ソートも、サーチも、あるんだよ」~標準C++ライブラリにみるアルゴリズムの面白さ
  29. インテルTBBの同期メカニズム
  30. なぜsetを使っちゃいけないの?
  31. WPFアプリケーションで腕試し ~C++でもWPFアプリを
  32. C++11 : スレッド・ライブラリひとめぐり
  33. Google製のC++ Unit Test Framework「Google Test」を使ってみる
  34. メールでデータベースを更新するココロミ
  35. Visitorパターンで遊んでみたよ
  36. Collection 2題:「WPFにバインドできる辞書」と「重複を許す検索set」
  37. Visual C++ 2012:stateless-lambdaとSQLiteのぷち拡張
  38. 「Visual C++ Compiler November 2012 CTP」で追加された6つの新機能

@IT

  1. Vista時代のVisual C++の流儀(前編)Vista到来。既存C/C++資産の.NET化を始めよう!
  2. Vista時代のVisual C++の流儀(中編)MFCから.NETへの実践的移行計画
  3. Vista時代のVisual C++の流儀(後編) STL/CLRによるDocument/Viewアーキテクチャ
  4. C++開発者のための単体テスト入門 第1回 C++開発者の皆さん。テスト、ちゃんとしていますか?
  5. C++開発者のための単体テスト入門 第2回 C++アプリケーションの効率的なテスト手法(CppUnit編)
  6. C++開発者のための単体テスト入門 第3回 C++アプリケーションの効率的なテスト手法(NUnit編)

AWARDS


Microsoft MVP
for Visual Developer - Visual C++


Wankuma MVP
for いぢわる C++


Nyantora MVP
for こくまろ中国茶

Xbox

Links

記事カテゴリ

書庫

日記カテゴリ

拡張メソッドの邪悪な用途

やりたいこと : インスタンスが null だったら (null) と書く...

public class foo {
  private int value;
  public foo(int v) { value = v; }
  public void print() {
    if ( this == null ) 
      System.Console.WriteLine("(null)");
    else
      System.Console.WriteLine(value);
  }

  public static void Main() {
    foo f;
    f = new foo(123);  f.print();
    f = null;          f.print(); // ←※
  }
}

※ 当然のことながら ぬるり(null 参照例外)が飛んできますね。
そんなアナタに拡張メソッド:

public static class fooExtension {
  public static void print(this foo f) {
    if ( f == null ) System.Console.WriteLine("(null)");
    else f.print_();
  }
}

public class foo {

  private int value;

  public foo(int v) { value = v; }
  internal void print_() {
    System.Console.WriteLine(value);
  }

  public static void Main() {
    foo f;
    f = new foo(123); f.print();
    f = null;         f.print(); // 無問題!
  }
}

投稿日時 : 2009年1月29日 9:32

コメントを追加

# re: 拡張メソッドの邪悪な用途 2009/01/29 10:04 えと

邪悪ですか?
null 安全なのでバリバリ使ってるんですけど。

# re: 拡張メソッドの邪悪な用途 2009/01/29 10:10 επιστημη

呼ぶ側がnullか否かを気にしなくていいんだけど、
拡張メソッドで"うまく逃げた"感が...ね。
# ぶざまに逃げたんじゃないからむしろ上策なのかしらん...

# re: 拡張メソッドの邪悪な用途 2009/01/29 10:25 出水

C++だとなんら問題ない…と思ったらvfptr参照するとまずいなぁ…

# re: 拡張メソッドの邪悪な用途 2009/01/29 10:31 えと

Java でいう Commons の StringUtils はほとんどのメソッドが null 安全で、C#2.0 でも多くの人が StringUtils を参考に自分の StringUtils を作ってたと思うんですよね。
それの第一引数に this を付けて import するだけであたかも String のメソッドのように呼び出せるとなれば、そうするんじゃないですかね。
それによって言語との差異が生じたとしても、許容範囲かなー、と。

> if ( this == null )
これが出来たらいいですよね。
別に拡張したいわけじゃなくて、単に null 安全なメソッドが欲しいだけの場合もあるわけですし。
そういう意味では本来の拡張メソッドの意義とは異なるので、邪悪かもしれません。
null の this ポインタを暗黙にでも明示的にでも経由したアクセスが発生した時点で NullReferenceException が投げられるような言語があってもいいと思うんですよね。

# re: 拡張メソッドの邪悪な用途 2009/01/29 10:40 επιστημη

うんうんう。

C++だと仮想関数呼ばなきゃ無問題です > nullインスタンスのメソッド呼び出し
# 仮想関数だったら NVI すりゃいぃんですけどね♪

# re: 拡張メソッドの邪悪な用途 2009/01/29 11:35 インドリ

LISP風にnilにしないのですか?

# re: 拡張メソッドの邪悪な用途 2009/01/29 11:36 επιστημη

LISP風にする必然性がありませんから♪

# re: 拡張メソッドの邪悪な用途 2009/01/29 11:49 インドリ

>LISP風にする必然性がありませんから♪

が~んw

# re: 拡張メソッドの邪悪な用途 2009/01/29 12:07 インドリ

>ぬるり(null 参照例外)が飛んできますね。

最初ここ読んだ時「ぬらりひょんが飛んでくる」と誤読したピヨw

# re: 拡張メソッドの邪悪な用途 2009/01/29 12:15 aetos

なんかね、なまじインスタンスメソッド風に見えるだけに気持ち悪いです。

# re: 拡張メソッドの邪悪な用途 2009/01/29 12:38 アキラ

C#は元々、インスタンスメソッドとクラスメソッドの呼び出しを.と::で分けてませんからねぇ。

でも、C++でもoperator.がオーバーロードできたら同じことやりますよw

# re: 拡張メソッドの邪悪な用途 2009/01/29 12:59 デフォルトの名無しさん

> C++だと仮想関数呼ばなきゃ無問題です > nullインスタンスのメソッド呼び出し
いいえ。未定義動作になり得ます。

このため、極端な話、コンパイラは
メンバ関数内での (this == 0) を false に
最適化することもできるはずです。

C++2003 では 1.9 p4 に未定義動作の例として
「ヌルポインタをデリファレンスした場合の動作」が
載っていることが根拠となり得ます。

ただ、明示的に禁止する記述がないうえに、別の
箇所ではヌルポインタをデリファレンスしたあとの
動作を説明している箇所もあり、一貫して
いないので修正が必要だという Defect Report が
挙がっています。
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232

まだ drafting ということで C++0x には
間に合わなかったみたいですが、提案されている
修正から将来的にもヌルポインタからの
メンバ関数呼び出しは未定義動作になる見通し
です。

# re: 拡張メソッドの邪悪な用途 2009/01/29 13:15 επιστημη

ふぉろーありがとです。
# 同じネタで cppll にも投げといたんですけどね ^^;

「たまたまほとんどの処理系で動いてるだけ」
って扱いですかねー > nullインスタンスのメソッド呼び出し

# re: 拡張メソッドの邪悪な用途 2009/01/29 14:17 Imabeppu

たまたまというより、独自拡張という感じですかね。
VC++ は CWnd::GetSafeHwnd() で利用してますんで。

# re: 拡張メソッドの邪悪な用途 2009/01/29 14:34 επιστημη

> C++2003 では 1.9 p4 に未定義動作の例として
>「ヌルポインタをデリファレンスした場合の動作」が
> 載っていることが根拠となり得ます。

裏を返せば、「(仮想関数でない)メンバ呼び出しの際にthisの参照外しは行われない。」
ことを言語仕様として保証しないから未定義動作と。

で、VC++に代表される現役の多くの処理系では「....」だからOKと。

# re: 拡張メソッドの邪悪な用途 2009/01/30 2:32 デフォルトの名無しさん

> 裏を返せば、「(仮想関数でない)メンバ呼び出しの際にthisの参照外しは行われない。」
> ことを言語仕様として保証しないから未定義動作と。

規格中や Defect Report でのデリファレンス(参照外し)とは
ポインタに対して "*" を適用することで、実際にポインタの
指すオブジェクトにアクセスするかどうかは関係ありません。
"p->" は "(*p)." と定義されているので、演算子 "->" の適用は
必ずデリファレンスを伴うことになります。

用語の意味は別として、多くの処理系で問題が起こらない理由が、
仮想関数でないメンバ関数呼び出しの際に this の指す
オブジェクトにアクセスする必要が無いからである、というのは
そのとおりだと思います。

# wgRraDAOyEdB 2022/04/19 10:57 johnansaz

http://imrdsoacha.gov.co/silvitra-120mg-qrms

タイトル
名前
URL
コメント