MarshalByRefObjectから継承する

小ネタ。

通常、MarshalByRefObjectから継承することはあまり無いとは思いますが、RealProxyを使ったAOPモドキなんかで、ひょっとしたら使うことがあるかも知れません。その場合のデメリットを見てみましょう。

using System;
using System.Diagnostics;

namespace MarshalByRefSample
{
    /// <summary>
    /// MarshalByRefObjectから継承
    /// </summary>
    class Foo : MarshalByRefObject
    {
        public int Counter;
    }

    /// <summary>
    /// Objectから継承
    /// </summary>
    class Bar
    {
        public int Counter;
    }

    class Program
    {
        static void Main(string[] args)
        {
            const int max = 10000000;

            var foo = new Foo();
            var sw = Stopwatch.StartNew();
            for (var i = 0; i < max; ++i)
                foo.Counter++;
            sw.Stop();
            Console.WriteLine("{0}:Counter={1}, Time={2}", foo.GetType(), foo.Counter, sw.ElapsedMilliseconds);

            var bar = new Bar();
            sw = Stopwatch.StartNew();
            for (var i = 0; i < max; ++i)
                bar.Counter++;
            sw.Stop();
            Console.WriteLine("{0}:Counter={1}, Time={2}", bar.GetType(), bar.Counter, sw.ElapsedMilliseconds);
        }
    }
}
/* 結果
MarshalByRefSample.Foo:Counter=10000000, Time=901
MarshalByRefSample.Bar:Counter=10000000, Time=31
 */

フィールドへのアクセスは自動的にプロキシ経由(+リフレクション)になるため、大きなオーバーヘッドがかかります。あと記憶では、インライン展開の最適化の対象外になったはず(プロキシ経由なので当たり前と言えば当たり前)。