delegateの寿命

先日のid:NyaRuRuさんのツッコミを実際に試してみました。

//hoge.dll
#include <stdio.h>
extern "C" {
  typedef const char* (*message)();
  static message s_fn = 0;
  __declspec(dllexport) void set( message msg ){
    s_fn = msg;
  }
  __declspec(dllexport) void say(){
    printf("%s\n",(*s_fn)());
  }
}
  delegate string WhatDoYouSay();
  [DllImport("hoge.dll")]
  static extern void set(WhatDoYouSay callback);
  [DllImport("hoge.dll")]
  static extern void say();
  static string ISay(){
    return "Good Morning!!";
  }
  static void Main(string[] args){
    WhatDoYouSay fn = new WhatDoYouSay( ISay );
    set(fn);
    say();//ok
    say();//ok
    //参照を消してガベコレ発動
    fn = null;
    GC.Collect();
    GC.WaitForPendingFinalizers();

    say();//error!!
  }

見事最後のsayでハングしました。delegate型とメソッド型は異なるモノってのを覚えておかないといけませんね。先日のコードだと暗黙に変換(バインド?)されてるのでうっかりミスしちゃいそう。