この質問は、ジェネリック型仕様の引数を含める必要がある場合と含める必要がない場合に関するものです。少し長いのでご容赦ください。
次の(考案された)クラスがある場合...
public abstract class UserBase
{
public void DoSomethingWithUser() { }
}
public class FirstTimeUser : UserBase
{
/* TODO: some implementation */
}
次の方法...
private static void DoThingsWithUser<TUser>(TUser user) where TUser : UserBase
{
user.DoSomethingWithUser();
}
type引数を指定する必要がある場合とない場合で呼び出すことができますTUser
...
var user = new FirstTimeUser();
DoThingsWithUser<FirstTimeUser>(user);
DoThingsWithUser(user); // also valid, and less typing required!
ここまでは順調ですね。
しかし、さらにいくつかの(再び考案された)クラスを追加すると...
public abstract class UserDisplayBase<T> where T : UserBase
{
public T User { get; protected set; }
}
public class FirstTimeUserDisplay : UserDisplayBase<FirstTimeUser>
{
public FirstTimeUserDisplay()
{
User = new FirstTimeUser();
}
}
そして方法...
private static void DoThingsWithUserDisplay<TDisplay, TUser>(TDisplay userDisplay)
where TDisplay : UserDisplayBase<TUser>
where TUser : UserBase
{
userDisplay.User.DoSomethingWithUser();
}
このメソッドを呼び出す場合、必須型引数を含めるように...
var userDisplay = new FirstTimeUserDisplay();
DoThingsWithUserDisplay<FirstTimeUserDisplay, FirstTimeUser>(userDisplay); // Type arguments required!
型引数を指定しない場合、次のコンパイラエラーが発生します。
メソッド 'DoThingsWithUserDisplay(TDisplay)'の型引数は、使用法から推測できません。型引数を明示的に指定してみてください。
私が考えて、コンパイラが/このアウトを理解するために、スマートに十分な可能性がなければならないこと...かなぜない微妙な理由があるのでしょうか?
コンパイラーが推測する型を分析しているので、見ると行き止まりになります DoThingsWithUserDisplay(userDisplay);
それはTDisplay
タイプでなければならないことがわかりFirstTimeUserDisplay
ます。これは良いことです。次に、制約は、TDisplay
から継承する必要があることを示しUserDisplayBase<TUser>
ます。
の型がわからTUser
ないため、FirstTimeUserDisplay
継承元かどうかを判断できずUserDisplayBase<TUser>
、またTUser
、ジェネリックにある型が何であれ、パラメータを推測することもできませんUserDisplayBase<TUser>
。
編集:ちなみに、バリアントとのインターフェイスを使用して、探している型推論を取得できます。この場合、インターフェース定義は、制約が満たされるように十分な継承情報を提供します。
public abstract class UserDisplayBase<T> : IUserDisplayBase<T>
where T : UserBase
{
public T User { get; protected set; }
}
public interface IUserDisplayBase<out T>
where T : UserBase
{
T User { get; }
}
private static void DoThingsWithUserDisplay<TDisplay>(TDisplay userDisplay)
where TDisplay : IUserDisplayBase<UserBase>
{
userDisplay.User.DoSomethingWithUser();
}
で呼び出すことができます
var userDisplay = new FirstTimeUserDisplay();
DoThingsWithUserDisplay(userDisplay);
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加