C# こわい話: LINQ でパスのサニタイズしたくらいでテストが通らないなんてそんな事が
起きた😅
現象
public static class x { public static string f( string input ) { var targets = Path.GetInvalidFileNameChars(); var intermediate = from c in input where !targets.Contains( c ) select c; var result = string.Concat( intermediate ); // <-- 予想外の結果が生じていた return result; } }
input
に "Death Sauce \n\r 02:00:00"
を与えてテストしたら "Death Sauce 020000"
が Expected 、と思ったんだけど、実際に出たのは "System.Linq.Enumerable+WhereEnumerableIterator
1[System.Char]"` でした💀
対策
var result = new string( intermediate.ToArray() );
string
は char[]
からのコンストラクターを持っているのでこれで Actual == Expected へ。
この問題に気づいて初め、ほぼワンライナー程度の実装なのでテスト側のコードにべたっと書いてデバッガー挿したら期待動作しちゃったんだよね。ぇー…って思って wandbox で最小コード切り出して叩いても期待動作して再現しないし。
ローカル環境では放り込むアセンブリーの単位を変えたら発症したので、そこらへんに理由があって、古い .NET Framework ターゲットでは string.Concat
のオーバーロード解決がナウい処理系とは異なるとかなのかな。もっと単純に何か私がミスしてるのかな🤔
回避方法は上記の通り簡単だし、この処理はボトルネックでもなんでもないのでさくっと回避して通り過ぎる事にしたけれど、お気持ちは少々もんにょりが残る。なんじゃろ。