usingの闇

More Effective C#を読んでいて、ふとusingの知らない使い方を発見。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace UsingSample
{
    class Foo : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("Dispose");
        }
    }

    class Program
    {
        static void Test<T>() where T :  new()
        {
            // TがIDisposableを実装している場合だけDisposeしたい
            /* コンパイルできない
            using (T t = new T())
            {
            }
            */

            T t = new T();

            try
            {
                Console.WriteLine("Do anything...");
            }
            finally
            {
                if (t is IDisposable)
                    (t as IDisposable).Dispose();
            }            
        }

        static void Test2<T>() where T : new()
        {
            T t = new T();
            // Tの型は無視して、無理矢理as
            using (t as IDisposable)
            {
                Console.WriteLine("黒魔術...");
            }
        }

        static void Main(string[] args)
        {
            Test<int>();
            Test<Foo>();
            Test2<int>();
            Test2<Foo>();
        }
    }
}

/* 結果
Do anything...
Do anything...
Dispose
黒魔術...
黒魔術...
Dispose
 */

便利だけど、釈然としないものが。C#は時々予期しないコードを吐くことがありますが、usingも色々やってくれていますね。