null の扱い
Maybe つながりで、色んな言語の null の扱いについてちょっとだけまとめてみた。
観点は一つ、「this が null の場合に this の指す先にアクセスしないメソッドが呼び出せるか」です。
C++
#include <iostream> struct hoge { void f() { if (this == 0) std::cout << "this is null." << std::endl; else std::cout << "this is not null." << std::endl; } }; int main() { hoge* h = 0; h->f(); // => this is null. }
できます。
追記:
ideone で試してできただけで、未定義動作でした。(thx: id:uskz)
参考:API Only - Stack Exchange
Java
public class Main { void f() { if (this == null) System.out.println("this is null."); else System.out.println("this is not null."); } public static void main(String[] args) { Main x = null; x.f(); // NullPointerException } }
できません。
C#
class Program { void F() { if (this == null) System.Console.WriteLine("this is null."); else System.Console.WriteLine("this is not null."); } public static void Main() { var x = default(Program); x.F(); // NullReferenceException } }
できません。が、拡張メソッドを使うと見た目上はできるように書けます。
class Program { public static void Main() { var x = default(Program); x.F(); // NullReferenceException } } static class ProgramExt { public static void f(this Program self) { if (self == null) System.Console.WriteLine("this is null."); else System.Console.WriteLine("this is not null."); } }
F#
[<AllowNullLiteral>] type Hoge() = member x.f() = if x = null then printfn "this is null." else printfn "this is not null." let x: Hoge = null x.f() (* => this is null. *)
できます。null リテラルを直接使いたい場合、AllowNullLiteral 属性を付けなければならない点に注意してください。
JSX
class _Main { function f(): void { if (this == null) log "this is null."; else log "this is not null."; } function main(args: string[]): void { var x: _Main = null; x.f(); // Type Error: Cannot call method 'x$' of null } }
できません。
まとめ?
レシーバをメソッドの隠れた引数と考えるのであればできるし、そうじゃないナニモノかであると考えるのであればできない、ということでしょうか。
レシーバが null とはどういうことだ!けしからん!!とかってなって即ぬるぽ。
これができることによる問題って思いつかないんだけど、何かあるんだろうか。