中堅プログラマーの備忘録

忘れっぽくなってきたので備忘録として・・・

【C#.net】関数からの戻り値を複数取得したい・・・Tuple型を使う

1.概要

例えば下記のようなファイルを削除する関数があります。

private bool FileDelete(string filePass)
{
    try
    {
        System.IO.File.Delete(filePass);
        return true;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.GetType().FullName + ":" + ex.Message);
        return false;

    }
}

削除が成功したら【true】、削除が失敗したら【false】
を戻り値として返します。


【true】だった場合は問題にならないのですが
【false】だった場合、何故失敗したのか?がわかりません。
わからないということは原因不明のエラーに悩まされてしまうことになります。

2.参照渡しを使う方法

【C#】において引数は【値渡し】であることが一般的です。
一般的ということは例外も存在するということで
これが【参照渡し】になります。
【参照渡し】の方法としては【ref】と【out】が存在します(【in】は省略)

違いを簡単に説明すると

【ref】呼び出し元の変数を関数に渡すと、変化して戻ってくる

【out】呼び出し元の空の変数を関数に渡すと、値が入って戻ってくる

上記のような感じかと思います。

今回は戻り値を複数取得したいだけなので【out】を使います。
先程のファイルを削除する関数を下記のように変更しました。

private void FileDelete(string filePass, out bool argRes, out string argStr)
{
    try
    {
        System.IO.File.Delete(filePass);
        argRes = true;
        argStr = "";
    }
    catch (Exception ex)
    {
        argRes = false;
        argStr = ex.GetType().FullName + ":" + ex.Message;
    }
}


呼び出し元には下記のとおり記述します。

bool res;
string str;
FileDelete(@"C:\test\test.txt", out res, out str);


結果としては

res = false
str = System.IO.IOException:別のプロセスで使用されているため、プロセスはファイル 'C:\\test\\test.txt' にアクセスできません。

となりました。
※ファイル使用中のエラーを模擬

3.Tuple型を使う方法

C# 6までは【参照渡し】が戻り値を複数返す唯一の方法でしたが
C# 7から【Tuple型】が追加されました。
【参照渡し】で問題だった、非同期メソッドでは使用できないという問題も
【Tuple型】では解消されています。


では、例によってファイルを削除する関数を下記のように変更しました。

private ValueTuple<bool, string> FileDelete(string filePass)
{
    ValueTuple<bool, string> result;
    try
    {
        System.IO.File.Delete(filePass);
        result.Item1 = true;
        result.Item2 = "";
    }
    catch (Exception ex)
    {
        result.Item1 = false;
        result.Item2 = ex.GetType().FullName + ":" + ex.Message;
    }

    return result;
}

呼び出し元には下記のとおり記述します。

var res = FileDelete(@"C:\test\test.txt");

結果ですが

result.Item1 = false
result.Item2 = System.IO.IOException:別のプロセスで使用されているため、プロセスはファイル 'C:\\test\\test.txt' にアクセスできません。

となりました。

4.使ってみた感想

呼び出し元で変数を宣言する必要がない分
【Tuple型】を使う方がすっきりしたといったイメージです。


ただ、慣れてないので今のところ使い勝手は悪いです・・・


ちなみに開発環境が【Visual Studio 2015】だったので
【System.ValueTuple】をNugetからインストールする必要がありました。

これをしないと構文エラーが出てしまいます。