1

我有以下的類 -ASP.NET MVC 3視圖,超類不適用於子類?

public abstract class BusinessObject { } 
public abstract class Form: BusinessObject { } 
public abstract class BillableForm: Form { } 
public class MembershipForm: BillableForm { } 

public abstract class Dto<T>: where T: BusinessObject { } 
public abstract class InboxDto<T>: Dto<T> where T: Form { } 
public class MembershipFormDto: InboxDto<MembershipForm> { } 

和我有以下幾點看法 -

membershipform.cshtml: 
@model AdminSite.Models.MembershipFormDto 
@{ 
    Layout = "~/Views/Inbox/Shared/_LayoutForm.cshtml" 
} 

_LayoutForm.cshtml: 
@model InboxDto<Form> 

當我降落membershipform.cshtml頁面上,我得到以下異常說明:

傳遞到字典中的模型項目類型爲'AdminSite.Models.MembershipFormDto',但該字典需要一個'AdminSite.Infrastructure.Models.InboxDto`1 [BusinessLogic.Inbox.Form]'類型的模型項目。

從一切我可以告訴,MembershipFormDto IS-A MembershipForm類型,其中MembershipForm IS-A FormInboxDto。是什麼賦予了?

+0

您可以發佈您的操作方法的代碼? – Chandu

+0

異常不是來自操作方法。當我切換'_LayoutForm.cshtml'使用'@model dynamic'時,action方法工作正常,但我寧願有一個強類型模型。這可能是C#鍵入系統的一個問題,也是我的一些無知。 – MushinNoShin

回答

2

這原來是一個協變問題。

添加以下接口 -

public interface IInboxDto<out T> 

和修改InboxDto類來實現該接口 -

public abstract class InboxDto<T>: Dto<T>, IInboxDto<T> where T: Form { } 

總之,協方差是從多個定義類型要較少定義的類型;特別是引用定義較少的引用的更多定義的對象。編譯器會抱怨的原因是它的預防方案是這樣的:

List<String> instanciatedList = new List<String>; 
List<Object> referenceList = instanciatedList; 
referenceList.add(DateTime); 

最後一行是有道理的,一個DateTime IS-A Object。我們說referenceListObjectList。然而,它的實例爲StringList。 A ListObjectStringList更寬容。突然從new List<String>我們的保證被忽略。

Interface定義的關鍵字和關鍵字告訴編譯器放鬆,我們知道我們正在做什麼並理解我們正在做的事情。

More information.

+1

3個小時的這個問題摔跤,直到我終於問到這個問題。然後我需要20分鐘才能找到答案。勒嘆。 – MushinNoShin

+0

那麼,通常定義問題的過程會讓我們更清楚地思考問題,並且經常會促使我們認識到問題。這是一個很好的問題,雖然你的解決方案的工作..我會告誡任何人不知道他們在做什麼要小心。 –

+0

是的,任何時候人們都會告訴編譯器退後一步,他們隱含地聲稱他們知道危險是什麼。這裏是龍:) – MushinNoShin