2010-02-03 22 views
6

Questo è il mio set up,Come fare un elenco generico uguale un altro elenco generico

class CostPeriodDto : IPeriodCalculation 
{ 
    public decimal? a { get; set; } 
    public decimal? b { get; set; } 
    public decimal? c { get; set; } 
    public decimal? d { get; set; } 
} 

interface IPeriodCalculation 
{ 
    decimal? a { get; set; } 
    decimal? b { get; set; } 
} 

class myDto 
{ 
    public List<CostPeriodDto> costPeriodList{ get; set; } 

    public List<IPeriodCalculation> periodCalcList 
    { 
     get 
     { 
      return this.costPeriodList; // compile error 
     } 
    } 
} 

Quale sarebbe il modo migliore di fare questo?

risposta

3

Prova return this.costPeriodList.Cast<IPeriodCalculation>().ToList().

9

Uso Cast<IPeriodCalculation>():

public class CostPeriodDto : IPeriodCalculation 
{ 
    public decimal? a { get; set; } 
    public decimal? b { get; set; } 
    public decimal? c { get; set; } 
    public decimal? d { get; set; } 
} 

public interface IPeriodCalculation 
{ 
    decimal? a { get; set; } 
    decimal? b { get; set; } 
} 

public class myDto 
{ 
    public List<CostPeriodDto> costPeriodList { get; set; } 

    public List<IPeriodCalculation> periodCalcList 
    { 
     get 
     { 
      return this.costPeriodList.Cast<IPeriodCalculation>().ToList();   
     } 
    } 
} 

Credo in C# 4, se si sta utilizzando qualcosa di attuazione IEnumerable<out T>, si potrebbe semplicemente farlo nel modo che hai scritto, e che sarebbe stato risolto utilizzando Covariance.

class myDto 
{ 
    public IEnumerable<CostPeriodDto> costPeriodList{ get; set; } 

    public IEnumerable<IPeriodCalculation> periodCalcList 
    { 
     get 
     { 
      return this.costPeriodList; // wont give a compilation error  
     } 
    } 
} 
1

I metodi LINQ di trasmettere da una sequenza all'altra non saranno uguali . Ciò vuol dire che il seguente test fallirebbe se si fosse utilizzato Cast()/ToList().

Assert.AreSame(myDto.costPeriodList, myDto.periodCalcList); 

Inoltre, l'utilizzo di tali metodi significa che se si è tentato di aggiungere un elemento a una collezione, non sarebbero riflesse nell'altro. E ogni volta che hai chiamato periodCalcList, creava una collezione completamente nuova che poteva essere disastrosa a seconda di quanti oggetti, con che frequenza si chiamava, ecc.

Una soluzione migliore, a mio parere, è di non usare List<T> per tenendo premuto il CostPeriodDto e invece utilizzare una raccolta derivata da Collection<T> e implementare esplicitamente IEnumerable<IPeriodCalculation>. Opzionalmente è possibile implementare IList<IPeriodCalculation> se necessario.

class CostPeriodDtoCollection : 
    Collection<CostPeriodDto>, 
    IEnumerable<IPeriodCalculation> 
{ 

    IEnumerable<IPeriodCalculation>.GetEnumerator() { 
     foreach (IPeriodCalculation item in this) { 
      yield return item; 
     } 
    } 

} 

class MyDto { 
    public CostPeriodDtoCollection CostPeriods { get; set; } 
    public IEnumerable<IPeriodCalculation> PeriodCalcList { 
     get { return CostPeriods; } 
    } 
}