私は、コンパイル時の強力な型チェックに焦点を当てた流暢な引数アサーション ライブラリを実装しています。Intellisense は、アサートされた型で使用可能なメソッドと拡張機能のみを表示する必要があります。
IEnumerable の拡張機能を作成するときに、適切な型引数を解決できません。
ライブラリのアイデアは、IAssertion 型のアサーション インスタンスを返す任意の型で ThrowIf (または ThrowIfNot) を呼び出すことができるということです。
public static IAssertion<T> ThrowIf<T>(this T t)
{
return new IfAssertion<T>(t);
}
IEnumerable に特定のアイテムが含まれているかどうかを確認したいと思います。2 つのオーバーロードがあり、1 つは型 T のオブジェクトをパラメーターとして受け取り、もう 1 つは評価を行う関数を受け取ります。
public static T1 Contains<T1, T2>(this IAssertion<T1> assertion, T2 item)
where T1 : IEnumerable<T2>
{
// assertion logic
return assertion.Value;
}
public static T1 Contains<T1, T2>(this IAssertion<T1> assertion, Func<T2, bool> func)
where T1 : IEnumerable<T2>
{
// assertion logic
return assertion.Value;
}
実際の型のインスタンスを取るオーバーロードを使用すると、すべてがうまくいきます。ただし、関数コンパイラを使用した後者は、キャストが行われない限り、型引数を適切に推論できません。
var list = new List<string>();
list.ThrowIf().Contains("foo"); // compiles
list.ThrowIf().Contains((string s) => false); // compiles
list.ThrowIf().Contains(s => false); // does not compile
関数パラメーターのキャストを行わずにコンパイラーを満足させる方法はありますか?
実装の詳細については、 https ://bitbucket.org/mikalkai/argument-assertions/overview を参照してください。