1

List の代わりに IEnumerable を使用することに関する最初の提案の後に編集されました。

私はこれをやろうとしています:

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>'

暗黙的または明示的にそれを行うことはできません。これを行う方法はありますか?

前もって感謝します、

--- アリステア。

4

5 に答える 5

4
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
于 2012-09-18T11:44:32.493 に答える
1

あるタイプのリストを別のタイプにキャストしないでください。そうすると、挿入操作が失敗するか、取得が失敗します。

例:タイプ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参照に割り当てることができるという事実が損なわれます。

于 2012-09-18T11:49:04.323 に答える
1

これらの 2 つのリストは、たとえAirTemp_KPIDetailsmy が aであってもIKPIDetails(つまり、is-a関係を持っています)、異なります。あるリストから別のリストに要素をコピーする必要があります。

kpiDetailsList = new List<IKPIDetails>(airTempKPIList);

一般に、これは共分散と反分散の主題に属します。共分散と反分散 (コンピューター サイエンス)に関する Wiki 記事を参照してください。

于 2012-09-18T11:45:21.030 に答える
0

派生型ではなく、インターフェイスのリストとしてリストを作成する必要があります。

List<IKPIDetails> d = new List<IKPIDetails>();
于 2012-09-18T11:46:20.390 に答える
0

Try to use the below code.

public override List<IKPIDetails> MakeReportDataStructure() 
{ 
    return new List<AirTemp_KPIDetails>() as List<IKPIDetails>; 
}
于 2012-09-18T11:55:13.480 に答える