[C#]using

C#

Javaではパッケージ、他クラス使うとかでimportを使います。
C#では名前空間、他クラス使うとかではusingを使います。

JavaとかC#とか(他は知らないw)にあるGC。
使い終わったオブジェクトを破棄してくれる優れもの。
初めて聞いたときはすごいじゃん!とか思ってたら

            いつか破棄してくれる

という事に笑った記憶があるGCです。

例えば

Sample s = new Sample();
//処理
s = null;

こんな感じでnullを代入して誰からも参照されなくなった時とか

public void Sample()
{
	Sample s = new Sample();
	//処理
}

こんな感じでnullは入れてないけどスコープを抜けた時とか

このような時にGCさんが重い腰を上げてくれますね

いつか

ではこのような場合はどうだろうか

public void FileUp() 
{
    FileStream fs = new FileStream("ファイルパス", FileMode.Open, FileAccess.Read, FileShare.None);
    StreamReader sr = new StreamReader(fs);
    Console.WriteLine(sr.ReadToEnd());
}

スコープから抜けるからGCさんの獲物になりそうな予感がします。
ただ、このストリームは閉じられていません。
なのでこのテキストファイルはGCさんが働いてくれないとずっと開きっぱなしになります。(この例だと、開きっぱなしなので他の人もオープンできない)
StreamReaderクラスのClose()を使ってしっかり閉めてあげないといけません。

そもそもJavaでもトイレの扉でも開けたら閉めるのは常識ですね。

閉めるだけのClose()ではなく便利なものがあります。
IDisposableインターフェースの使い終わったリソースを解放するためのDispose()というメソッドがあります。
Close()ではなくDispose()ひとつでOKです。

使い方としては

public void FileUp()
{
    FileStream fs = new FileStream("ファイルパス", FileMode.Read);
    try {
        StreamReader sr = new StreamReader(fs);
        try {
            //処理
            sr.Dispose();
            fs.Dispose();
        }
        catch () {
            //例外処理
        }
    }
    catch () {
        //例外処理
    }
}

Close()の代わりに使う感じですね。
ただこの例だと、処理の時に例外が発生してしまった場合にDispose()を通りません。
なのでfinallyブロックを作ってあげることが必須です。

public void FileUp()
{
    FileStream fs = new FileStream("ファイルパス", FileMode.Read);
    try {
        StreamReader sr = new StreamReader(fs);
        try {
            //処理
        }
        catch () {
            //例外処理
        }
        finally {
            if (sr != null) {
                sr.Dispose();
            }
        }
    }
    catch () {
        //例外処理
    }
    finally {
        if (fs != null) {
            fs.Dispose();
        }
    }
}

こんな感じですね、大したこと書いてないのにただ高さがありますね。

ここで本題なのですが、C#には自動でDispose()してくれる
using
というのがあります。Javaでいうtry-with-resourcesみたいな
先ほどの例を変えてみると。。。

public void FileUp() 
{
    using (FileStream fs = new FileStream("ファイルパス", FileMode.Read)) {
    using (StreamReader sr = new StreamReader(fs)) {
            try {
                //処理
            }
            catch () {
                //例外処理
            }
        }
    }
}

こんな感じで半分になりました!自動的にfinallyでDispose()してくれます。
便利。

ただ、インポートする時にusing使ってるんだから違うキーワードにしてくれても良いのに・・・
と思った愚痴の記事でした。

コメント

タイトルとURLをコピーしました