簡體   English   中英

返回清單 <interface> 在C#中

[英]returning a list<interface> in C#

在有關使用IEnumerable而不是List的初步建議之后進行了編輯。

我正在嘗試這樣做:

public interface IKPIDetails // Previously: interface IKPIDetails
{ 
    string name {get; set;}
    //...
}


public abstract class BaseReport
{
    public List<IKPIDetails> m_KPIDetails;  // Previously: list<IKPIDetails> m_KPIDetails;

    public BaseReport()
    {
        m_KPIDetails = MakeReportDataStructure();
        //...
    }
    public abstract List<IKPIDetails> MakeReportDataStructure(); // Previously: public abstract IKPIDetails MakeReportDataStructure();

    //...
}


public class AirTemp_KPIDetails : NetVisSolution.Reports.IKPIDetails // Previously: protected class AirTemp_KPIDetails : IKPIDetails
{
    #region IKPIDetails implementation
    private string _Name;
    public string Name
    {
        get { return _Name; }
        set { _Name = value; }
    }
    #endregion
    ...
}

public class SSAirTempSummaryReport : BaseReport
{
    public SSAirTempSummaryReport() : base ()
    {
        // Do any extra initialisation here
        m_reportName = "Air Temperature Summary Report";
    }

    //It now complains on the declaration below at the word
    // MakeReportDataStructure()
    public override IEnumerable<IKPIDetails> MakeReportDataStructure() // Previously: public override List<IKPIDetails> MakeReportDataStructure()
    {
        List<AirTemp_KPIDetails> d = new List<AirTemp_KPIDetails>();
        return  d;  // <-- this is where it used to break
    }

    //...
}

因此,我有一個報表數據對象接口,並可能有多個報表數據類實現此接口並添加其特定的額外位。 我有一個抽象的報告類,實現了通用的報告功能,並且有多個派生類,每個派生類都使用自己的報告數據類。

不幸的是,當我嘗試在派生類中創建報表詳細信息結構的列表並將其作為接口列表傳遞回基類時,它抱怨:

Cannot implicitly convert type 
'System.Collections.Generic.List<NetVisSolution.Reports.AirTemp_KPIDetails>' to 
'System.Collections.Generic.List<NetVisSolution.Reports.IKPIDetails>'

它不會讓我隱式或顯式地執行此操作。 有什么辦法可以做到這一點?

提前致謝,

---阿利斯泰爾。

public override List<IKPIDetails> MakeReportDataStructure()
{
    List<AirTemp_KPIDetails> d = new List<AirTemp_KPIDetails>();
    return  d;  // <-- this is where is breaks
}

應該:

public override List<IKPIDetails> MakeReportDataStructure()
{
    List<IKPIDetails> d = new List<AirTemp_KPIDetails>();
    return  d;
}

您的分配不起作用,因為在List<T> ,類型參數T不是協變的,也就是說,當T更具體時,不允許分配。 如果您使用IEnumerable ,您的代碼將正常工作:

public override IEnumerable<IKPIDetails> MakeReportDataStructure()
{
    List<AirTemp_KPIDetails> d = new List<AirTemp_KPIDetails>();
    return  d;  // <-- works, because T in IEnumerable is covariant
}

您可能會問,為什么IEnumerable是協變的? 嗯, IEnumerable只允許您讀取數據(因此協方差用<out T>標記),並且您不能向其中寫入任何對象。 List允許您將對象寫到集合中,並且會遇到危險,后來您會向該集合中寫入不太具體的類型,這可能會導致錯誤,因為不太具體的類型不能提供與更多派生類型相同的功能:

public override IEnumerable<BaseClass> MakeList()
{
    List<DerivedClass> d = new List<DerivedClass>();
    // ...
    return  d; // assume it would work
}

var l = MakeList();
l.Add(BaseClass); // now we added object of BaseClass to the list that expects object of DerivedClass, any operation on the original list (the one with List<DerivedClass> type could break

這兩個列表是不同的,即使AirTemp_KPIDetailsIKPIDetails (即具有is-a -relation關系)也是如此。 您必須將元素從一個列表復制到另一個列表:

kpiDetailsList = new List<IKPIDetails>(airTempKPIList);

總的來說,這屬於同方差和相反方差的主題。 您可能需要閱讀Wiki上有關協方差和相反方差的文章(計算機科學)

您不應該將一種類型的列表轉換為另一種類型,因為插入操作將失敗或獲取。

示例:類型A實現(擴展)類型B

List<A> listA;
List<B> listB;


((List<B>) listA).add(new B()); 

如果這是合法的,則可以通過放置比A更通用的內容來破壞listA不變式。

A a = ((List<A>) listB).get(); //like get first, or something similar

這將打破只有A對象可以分配給A引用的事實。

您必須將列表創建為接口列表,而不是派生類型:

List<IKPIDetails> d = new List<IKPIDetails>();

嘗試使用下面的代碼。

public override List<IKPIDetails> MakeReportDataStructure() 
{ 
    return new List<AirTemp_KPIDetails>() as List<IKPIDetails>; 
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM