Unit Test 実行時の config ファイルの引継ぎ

単体テスト実施時に、テスト対象メソッド内で設定値を参照している場合に、設定値を取得できずにテストが正常に動作しない場合があります。
これは、たとえばテスト対象のプロジェクトに含まれている Web.config や App.config ファイルは、テストプロジェクト側の設定ファイルではないからです。
したがって、テストプロジェクト内部に App.config ファイルを作成して、必要な設定値をテスト対象プロジェクトの設定ファイルからコピーすることで回避することができます。

一方、正しくコピーしている筈なのにテスト実行時にエラーになる場合もあります。
これは、NuGetパッケージインストール時に自動的に記述される設定値が正しくなかったり、テストを実行する側にもパッケージが必要だったりすることがあるためだと考えられます。
したがって、テストプロジェクトに App.config 作成した後に、テスト対象プロジェクトで使用している NuGet パッケージをテストプロジェクト側でもインストールすることで回避することができます。

以上、よくはまるので、この場にメモしておきます。

誕生日から年齢を計算

必要に応じて毎回書いていたのですが、面倒なのでメモしておくことにします。
まずは、次のようなメソッドにして算出する場合です。

int GetAge(DateTime birthday, DateTime? baseday = null) {
    var b = baseday ?? DateTime.Today; // 第2引数省略時はシステム日付時点の年齢を返す
    return (getNum(b) - getNum(birthday)) / 10000;
    int getNum(DateTime d) => d.Year * 10000 + d.Month * 100 + d.Day;
}

処理内容は単純で、二つの年月日を数値化して差を求めて 10000 で割った商を年齢として返しているだけです。
なぜ 10000 で割るのかというと、たとえば「1987年1月23日」なら 19870123 という数値になっているため、10000 で割ることで「年」の部分が取り出せるからです。
なお、getNum はローカル関数で、この機能は C#7 以降のみ対応です。

たとえば、以下のように使います。

var birthday = new DateTime(1989, 12, 1); // 誕生日
var age = GetAge(birthday); // 今日時点の年齢

必要に応じて計算したい場合は、以下のようにワンライナーで書くこともできます。

var age = ((t.Year * 10000 + t.Month * 100 + t.Day) - (b.Year * 10000 + b.Month * 100 + b.Day)) / 10000;

この方が高速ですし、わかりやすいかもしれません。

文字列を DateTime 型に変換

DateTime 型のプロパティ Date を実装した例です。
C#7 からは、以下のようなパターンで記述することが多くなりそうです。

public DateTime Date => 
    DateTime.TryParseExact(
	"20170123", 
	"yyyyMMdd", 
	CultureInfo.CurrentCulture, 
	DateTimeStyles.None, 
	out DateTime result) ? 
	    result : 
	    DateTime.Today;

文字列で表現された日付(時刻)が正しく DateTime 型に変換できた場合は、変換した結果の result の値を返します。
そうでなければ今日の日付を返します。

参考までに、以下のような書き方もできます。

public DateTime Date { 
    get {
        DateTime result;
        if (DateTime.TryParseExact(
            "20170123", 
	    "yyyyMMdd", 
	    CultureInfo.CurrentCulture, 
	    DateTimeStyles.None, 
	    out result)
        {
            return result;
        } 
	return DateTime.Today;
    }
}

なるべく式で書いた方が良いので、私は前者の書き方ですね。

ローカル関数を使用する

C#7 からローカル関数が使えるようになりました。
今までは、ひとつのメソッドが長くなりすぎた場合に、可読性を向上させる目的で下請けメソッドを宣言していました。

int Method() {
    :
    Shitauke();
    :
}

int Shitauke() {
    :
    :
}

ローカル関数を使うと、以下のように書くことができます。

int Method() {
    int Shitauke() {
        :
        :
    }
    :
    Shitauke();
    :
}

これによって、気軽に自身のメソッドブロック内に独立性の高い処理をメソッドアウトできるので、他のメソッドに干渉されることなく関連性の高いメソッドをまとめて読めるので積極的に使っています。
ただし、メソッドブロック内のコードの可読性が落ちます。
特に、ローカル関数の宣言部分と、メソッドのメインコードの区別がつかないところが悩ましいです。
いろいろ試してみた結果、次のように落ち着きました。

  1. ローカル関数名はキャメル表記にする
  2. ローカル関数の宣言はメソッドブロックの最後にまとめる
  3. そのメソッドの主処理の末尾に return ステートメントを記述する

ローカル関数名をキャメル表記にするのは、主処理が関数を呼び出すとき、他で宣言されているものかローカル関数かを明確にできるためです。
ローカル関数の宣言を最後にまとめる理由ですが、先頭にまとめると主処理がどこから開始されるのかを探さなければならないからです。
主処理の最後に return を記述する必要は本来はないのですが、これもどこまでが主処理の最後なのかを明確にするためです。

int Method() {
    :
    shitauke();
    :
    return;

    int shitauke() { // ローカル関数名はキャメル表記にする。
        :
        :
    }
}

ただし、これが正解かというと、いろいろな意見もありそうです。
とりあえず、しばらくは上記の規則いこうかと思います。

IEnumerable の遅延実行ではまる例

先ほど軽くはまったのでメモです。

次のコードは、正しく動作しません。

IEnumerable GetItems(){
    using (var db = CreateDataContext()) {
        return db.Table;
    }
}

void Main(){
    var items = GetItems();
    foreach(var x in items) {
        Console.WriteLine(x.Title);
    }
}

理由です。
db.Table に実際にアクセスされるのは、Main メソッドの foreach で items を使用した時点ですが、この時すでに DataContext インスタンスが破棄されているためデータベースにアクセスできずにエラーが発生します。

もう少し詳しく説明すると、GetItems メソッドが return している db.Table は IQueryable型です。
これは、データベースへのアクセスに関する定義を返すだけで、実際に取得したコレクションインスタンスを格納している訳ではありません。
一方 IQueryable 型は IEnumerable 型を継承しているため、GetItems メソッドのように暗黙の型変換が実行されています。
ここに気づかないとはまる訳です。
GetItems メソッドを以下のようにすると、正しく動作するようになります。

using (var db = CreateDataContext()) {
    return db.Table.ToList(); // ←変更
}

理由は、ToList メソッドで取得したデータからコレクションインスタンスを生成したものを返すためです。
簡単な理由ですが、実際の開発コードでは、複雑にメソッドが絡み合っていたりするので、軽くはまるのでメモしておきます。

デリゲートの宣言

以下のように名前を明確に示したいデリゲートがあったとします。

public delegate int HogeHoge(int value1, int value2);

今、次のような書き方を思いつきました。

    
using HogeHoge = Func<int, int, int>;

delegate を使って正しく宣言するか、using ディレクティブを使って別名で宣言するかの違いなんですけどね。
メモしておきます。

Entity Framework コードファーストとビューの扱い

いつのバージョンからなのかわからないけれど、ADO.NET.Entity Data Model が「新しい項目の追加」ダイアログボックスのテンプレートに追加されている。
これを使うと、既存のデータベースからコードファーストに必要なモデルを一式作成してくれる。
したがって、以後は次のようにすると良いのかもしれない。

1.コードファーストでさっくりとデータベースとテーブルを作ってあげるためのプロジェクトを作成
2.作成後のデータベースにビューなどを追加
3.必要に応じてテーブルやビューを変更したりする

実際のシステムを開発する場合は、DataModel なりのフォルダを切って、ここに ADO.NET.Entity Data Model からコードファーストモデルを作る。
マイグレーションの度に、DataModel フォルダ以下を削除して、再度 ADO.NET.Entity Data Model からコードファーストモデルを作る

これがベストな解かどうかはわからないけれど、ビューも管理できるし、しばらくはこれでいこうかな

null条件演算子の使い道

調べものをしていたら、以下のサイトの記事が目に留まってしまった。

http://qiita.com/tadnakam/items/a42d320f2bb19c69a004
C# 6.0 新機能まとめ(qiita)

この以下の部分

>4 Null条件演算子
>?. という演算子が追加されたそうです。null 以外のとき、値を変換するなどに使えそうですが、使う機会は少なそうです。

とありましたけど、自分は使った経験が何度かあったので気になりました。

?.演算子は、??演算子とセットで使用すると大変便利です。

if (r == null) {
    a = 0;
    b = "";
}
else {
    a = r.A;
    b = r.B;
}

の場合に、次のように書くことができます。

a = r?.A ?? 0;
b = r?.B ?? "";

r が null の時は、null と評価されるので ?? 演算子の右辺のオペランドが有効になるのですね。