2013-05-05 14 views
5

Ho la seguente classe sigillata. Sto cercando di restituire l'elenco come ReadOnlyCollection. Ho provato un paio di cose ma non ho capito. Quindi, come posso restituire o trasmettere l'elenco alla raccolta di sola lettura?Perché sto ricevendo errore: "non può convertire implicitamente il tipo System.Collections.Generic.List"

public sealed class UserValues 
    { 
     private readonly List<UserValue> _Values = new List<UserValue>(); 

     public ReadOnlyCollection<UserValues> Values 
     { 
      get 
      { 
       return _Values; 
      } 
     } 
    } 
+0

La classe 'List ' 'ha object' come la sua classe base. La classe 'ReadOnlyCollection ' non è quindi una classe base, e poiché non sono definiti operatori impliciti, non è possibile semplicemente convertire tra queste due classi in questo modo. Se vuoi creare un nuovo 'ReadOnlyCollection <>', usa '_Values.AsReadOnly()'. Se si utilizza la versione .NET più recente (4.5, VS2012), è possibile modificare il tipo di proprietà nell'interfaccia 'IReadOnlyList '. Poiché 'List <>' implementa 'IReadOnlyList <>', questo non richiede cast. Non è sicuro (se non ti fidi dei consumatori della tua classe). –

+0

Un consumatore determinato potrebbe utilizzare il reflection per ottenere il 'IList ' avvolto anche da un 'ReadOnlyCollection ', tuttavia - non c'è molto che puoi fare per impedire a qualcuno di fare scherzi con le interiora delle tue classi se davvero, davvero vogliono . Immagino che se * sono * determinati a rompere le cose, troveranno un modo, quindi non vale la pena preoccuparsi troppo. –

+0

Ho provato a fare _Values.AsReadOnly() come menzionato da Jeppe e ottenere lo stesso errore del compilatore. E sto usando solo vs2008, quindi non ho accesso all'interfaccia che ha menzionato. – Debbie

risposta

4

Prova:

return new ReadOnlyCollection<UserValue>(_Values); 

Edit:

Dato quello che hai detto a Jon, il codice non ha senso. Il tuo get fa riferimento a un tipo di List<UserValue>, ma tu vuoi convertirlo in un tipo di ReadOnlyCollection<UserValues>, che non può essere fatto - cioè 2 raccolte di 2 tipi diversi.

Avremo bisogno di ulteriori informazioni per aiutarti a rispondere a questa domanda. Desideri la tua classe UserValues per restituire una raccolta di tipi UserValues o una raccolta di tipi UserValue? Il tuo codice implica UserValue, ma i tuoi commenti su follow sono UserValues. Sei sicuro che il tuo supervisore non abbia fatto un refuso?

In caso contrario, avrete bisogno di un po 'di raccolta interna in questo modo:

private readonly List<UserValues> _MoreValues = new List<UserValues>(); 

e poi tornare che, nella sintassi che io (o altri che hanno risposto - tutte le risposte fornite sono valide per la conversione di un Elenco a ReadOnlyCollection) hanno mostrato.

Nota che il mio codice compila il targeting .Net 3.5, presumendo che i tipi siano compatibili (ovvero ReadOnlyCollection<UserValue> wraps List<UserValue>, o entrambi sono UserValues).

+0

Questo creerà una nuova istanza del wrapper 'ReadOnlyCollection ' ogni volta che si accede alla proprietà - probabilmente non è l'ideale. –

+0

È vero che non è "ideale", ma in questo caso risponde alla domanda e porta l'interrogante sulla sua strada. Si può fare .AsReadOnly come gli altri hanno suggerito, ma se si decompila si vede che lo fa: restituire nuovo ReadOnlyCollection ((IList ) this) ;. La soluzione "migliore" (a seconda delle esigenze della persona) sarebbe quella di creare un membro che detiene la raccolta di sola lettura, e restituirlo ... ma che sembrava oltre la portata della domanda, che era un problema di casting. – Gjeltema

+0

Ho appena avuto il tempo di provare il codice sopra e non verrà compilato neanche. – Debbie

3

che stai ricevendo l'errore di compilazione perché un List<UserValue> è non un ReadOnlyCollection<UserValue>, né è implicitamente convertibile in questo. (Presumo che volevi dire ReadOnlyCollection<UserValue> invece ReadOnlyCollection<UserValues> a proposito?)

E 'probabilmente più semplice da usare List<T>.AsReadOnly - ma si potrebbe anche creare solo una volta:

public sealed class UserValues 
{ 
    private readonly List<UserValue> values = new List<UserValue>(); 
    private readonly ReadOnlyCollection<UserValue> valuesView; 

    public UserValues() 
    { 
     valuesView = values.AsReadOnly(); 
    } 

    public ReadOnlyCollection<UserValues> Values { get { return valuesView; } } 
} 

Il ReadOnlyCollection<T> è in realtà solo una vista - quindi le modifiche alla raccolta sottostante saranno visibili attraverso la vista.

+0

Ciao Jon. No, volevo dire "UserValues" con una s. Il mio supervisore mi ha dato gli stub del codice e dovrei riempirli senza cambiare la firma del metodo. Questo sarebbe molto più semplice se potessi cambiare la firma in modo che corrisponda alla variabile. – Debbie

+0

@Debbie: Beh, il codice che hai scritto nella domanda ha molto poco senso. Sei sicuro che non sia un errore di battitura? Ti suggerisco di chiedere al tuo supervisore. Ha senso che una classe 'UserValues' abbia una collezione di oggetti' UserValue', ma non che abbia una collezione di oggetti 'UserValues'. –

2

_Values è un List<UserValue>, non un ReadOnlyCollection<UserValue> (che non sono collegate, per quanto riguarda il compilatore sa), quindi non è possibile tornare _Values direttamente. È possibile creare un ReadOnlyCollection<T> dalla vostra lista e restituire che, come:

private List<UserValue> _Values = [whatever]; 
private ReadOnlyCollection<UserValue> _ValuesWrapper; 

public UserValues() 
{ 
    _ValuesWrapper = _Values.AsReadOnly(); 
} 

public ReadOnlyCollection<UserValue> Values 
{ 
    get { return _ValuesWrapper; } 
} 

... o, se si sta solo cercando un modo di sola lettura di accesso al tuo raccolta e non hanno bisogno di un ReadOnlyCollection<UserValue> In particolare, è possibile modificare la proprietà per restituire un'interfaccia di sola lettura che implementa List<T> e l'applicazione potrebbe invece utilizzarla. .NET 4.5 ha introdotto alcune interfacce di raccolta di sola lettura che sono grandi per questo genere di cose:

public IReadOnlyList<UserValue> Values 
{ 
    get { return _Values; } 
} 
+0

Purtroppo non ho accesso a .net 4.5. Il mio studio di Visual è 2008. Fino ad ora, nulla di quanto menzionato qui funzionerà con la versione di Visual Studios che ho. Qualcuno può "sminuire" le loro risposte da .net 4.5 a .net 3.5, per favore? – Debbie

+0

Il mio codice compila il targeting .Net 3.5. Inoltre, la .AsReadOnly() che Jeremy e Jon hanno raccomandato è stata supportata da .Net 2.0, quindi anche la loro compilazione (http://msdn.microsoft.com/en-us/library/e78dcd75(v=vs.90) aspx). Il problema è legato alla necessità che la raccolta di oggetti 'UserValues' venga raccolta a mano libera in una classe di raccolta' UserValue'. Si prega di fornire maggiori informazioni come ho notato nella mia risposta per aiutarci a rispondere alla tua domanda. – Gjeltema

Problemi correlati