私はこのような公開機能を持っています:
public static T Get<T>(this Mango m, T defaultValue = default(T)) where T : class
{
//do something; return something;
}
public static T? Get<T>(this Mango m, T? defaultValue = default(T?)) where T : struct
{
//do something; return something;
}
基本的に、参照型とnull許容型を個別に処理したいと思います。コンパイルします。値型を要求するまで。参照型の場合はコンパイルします。
mango.Get<string>(); // compiles..
mango.Get(""); // compiles..
mango.Get<int>(); // The type 'int' must be a reference type in order to use it as
// parameter 'T' in the generic type or method Get<T>(Mango, T)
//also // The call is ambiguous between the following methods or properties:
// Get<int>(Mango, int) and Get<int>(Mango, int?)
ここにはどのような本当の曖昧さがありますか?の場合、構造体オーバーロードを適切に呼び出すことはできませんかT
?int
また:
mango.Get<int>(0); // The type 'int' must be a reference type in order to use it as
// parameter 'T' in the generic type or method Get<T>(Mango, T)
コンパイラが参照型の過負荷のみを検出するのはなぜですか?私は2つの別々のオーバーロードを試してみました:
public static T Get<T>(this Mango m) where T : class
{
return default(T);
}
public static T? Get<T>(this Mango m) where T : struct
{
return default(T);
}
public static T Get<T>(this Mango m, T def) where T : class
{
return default(T);
}
public static T? Get<T>(this Mango m, T? def) where T : struct
{
return default(T);
}
問題は解決しませんでした。そして明らかに、オーバーロードは単に制約に基づいて機能しないため、最初の2つのメソッドはここではコンパイルされません。
次のように、制約されたオーバーロードを削除し、class
制約されたオーバーロードだけを保持してみましたstruct
。
public static T? Get<T>(this Mango m, T? defaultValue = default(T?)) where T : struct
{
//do something; return something;
}
mango.Get<int>(); // voila compiles!
mango.Get<int>(0); // no problem at all..
// but now I can't have mango.Get<string>() for instance :(
2つの関数の名前を変更するだけですか?呼び出し元が実装の詳細を気にする必要がなくGet
、任意のタイプを呼び出すだけで済むように、名前を統一するのが適切だと思います。
更新:オプションのパラメーターを回避する必要がある場合、Marcのソリューションは機能しません。
mango.Get<int>(); // still wouldnt work!!
しかし、もっと魔法があります:( :(
public static bool IsIt<T>(this T? obj) where T : struct
{
return who knows;
}
public static bool IsIt<T>(this T obj) where T : class
{
return perhaps;
}
どうしても、同じコンパイラのバグ(私によると)が私を悩ませることを期待しています。しかし、今回は機能しません。
Guid? g = null;
g.IsIt(); //just fine, and calls the struct constrained overload
"abcd".IsIt(); //just fine, and calls the class constrained overload
したがって、Marcが言うように、制約チェックの前に過負荷の解決が行われる場合、今回も同じエラーが発生するのではないでしょうか。しかし、違います。なんでそうなの?一体何が起こっているのですか?:バツ