我試圖編譯下面的代碼:將混凝土類型澆鑄成普通類型?
public class BaseRequest<TResponse> where TResponse : BaseResponse {}
public class BaseResponse {}
public class FooRequest : BaseRequest<FooResponse> {}
public class FooResponse : BaseResponse {}
...
public TResponse MakeRequest<TResponse>(BaseRequest<TResponse> request)
where TResponse : BaseResponse
{
}
我希望我可以打電話MakeRequest(new FooRequest())
並獲得返回值FooResponse
。被叫方不必知道關於FooRequest
並可能將其傳遞給另一個處理程序。簽名工作正常,但我無法實現MakeRequest
方法。如果我實現它想:
public TResponse MakeRequest<TResponse>(BaseRequest<TResponse> request)
where TResponse : BaseResponse
{
FooRequest fooRequest = request as FooRequest;
if (fooRequest != null) // if I can handle the request, handle it
{
return new FooResponse(...); // ***
}
BarRequest barRequest = request as BarRequest;
if (barRequest != null)
{
return new BarResponse(...);
}
else // otherwise, pass it on to the next node
{
// maybe it will handle a BazRequest, who knows
return nextNode.MakeRequest(request);
}
}
但***
行不能編譯,因爲編譯器不知道FooResponse
是TResponse
。我知道這是因爲它在FooRequest
中指定。有沒有辦法解決這個問題,而不涉及討厭的反思(在這種情況下,我寧願返回BaseResponse
)?
謝謝。
更新:我正在使用泛型來強制執行返回類型,因此調用站點完全知道該期待什麼。僅僅在這裏返回BaseResponse
會容易得多,但它將負責確定具體的返回類型給調用者而不是請求處理程序(當然瞭解所有關於輸入的知識)。
首先,不應該將該方法稱爲MakeResponse,因爲它返回一個TResponse?但更一般地說:如果你必須檢查一個事物的類型,並且對某些特定類型採取了一些特定的操作,那麼**你並不是首先編寫泛型代碼**,那麼爲什麼你要使用泛型*?如果你有特殊的邏輯知道如何將一個FooRequest變成一個FooResponse,那麼創建一個接受FooRequest並返回一個FooResponse的方法;沒有泛型要求。 – 2012-02-23 19:46:04
@Eric - 我正在制定一個責任鏈模式,在這個模式中路由節點只是傳遞消息,並且可能中間的某個節點識別請求並返回正確的響應。不過,我應該在代碼示例中說清楚。 – 2012-02-23 19:51:23
@forcey CoR不暗示任何關於泛型的知識,而實例類型的匹配不是泛型的目的。只需傳遞BaseRequests並使用'if(request is FooRequest){...}' – 2012-02-23 19:55:35