2013-05-05 36 views
5

Ich habe die folgende versiegelte Klasse. Ich versuche, die Liste als ReadOnlyCollection zurückzugeben. Habe ein paar Sachen ausprobiert, aber ich habe nicht den Dreh raus. Wie kann ich die Liste zurückgeben oder in die Readonly-Sammlung umwandeln?Warum bekomme ich Fehler: "kann nicht implizit Typ System.Collections.Generic.List konvertieren"

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

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

Die Klasse 'Liste ' 'hat object' als Basisklasse. Die Klasse 'ReadOnlyCollection ' ist daher keine Basisklasse, und da keine impliziten Operatoren definiert sind, können Sie nicht einfach zwischen diesen beiden Klassen konvertieren. Wenn Sie eine neue 'ReadOnlyCollection <>' erstellen möchten, verwenden Sie '_Values.AsReadOnly()'. Wenn Sie die neueste .NET-Version (4.5, VS2012) verwenden, können Sie den Eigenschaftstyp auf die Schnittstelle 'IReadOnlyList ' ändern. Da 'List <>' IReadOnlyList <> 'implementiert, erfordert dies keine Umwandlung. Es ist nicht so sicher (wenn Sie den Verbrauchern Ihrer Klasse nicht vertrauen). –

+0

Ein entschlossener Verbraucher könnte Reflektion verwenden, um an der 'IList ' durch eine 'ReadOnlyCollection 'auch zu bekommen, obwohl - es gibt nicht viel, was Sie tun können, jemanden mit den Innereien Ihrer Klassen zu stören, wenn sie wirklich, wirklich wollen . Ich denke, wenn sie entschlossen sind, Dinge zu brechen, werden sie einen Weg finden, also ist es nicht wichtig, sich zu viele Sorgen zu machen. –

+0

Ich habe versucht, _Values.AsReadOnly() als Jeppe erwähnt und den gleichen Compiler-Fehler erhalten. Und ich verwende nur vs2008, also habe ich keinen Zugang zu der Schnittstelle, die er erwähnt hat. – Debbie

Antwort

4

Versuchen:

return new ReadOnlyCollection<UserValue>(_Values); 

Edit:

Anbetracht dessen, was Sie zu Jon gesagt haben, Ihr Code keinen Sinn macht. Ihr get bezieht sich auf einen Typ von List<UserValue>, aber Sie möchten es in einen Typ von ReadOnlyCollection<UserValues> konvertieren, was nicht getan werden kann - das sind 2 Sammlungen von 2 verschiedenen Typen.

Wir benötigen weitere Informationen, um Ihnen bei der Beantwortung dieser Frage zu helfen. Möchten Sie Ihre UserValues Klasse eine Sammlung von UserValues Typen oder eine Sammlung von UserValue Typen zurückgeben? Ihr Code bedeutet UserValue, aber Sie folgen auf Kommentare Status UserValues. Sind Sie sicher, dass Ihr Vorgesetzter keinen Tippfehler gemacht hat?

Wenn nicht, müssen Sie einige interne Sammlung wie folgt:

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

Und dann die Rückkehr in die Syntax, die ich (oder andere, die geantwortet haben - alle gegebenen Antworten sind gültig für eine Umwandlung Liste zu einer ReadOnlyCollection) haben gezeigt.

Beachten Sie, dass mein Code Targeting .NET 3.5 kompiliert, vorausgesetzt, dass die Typen kompatibel sind (dh ReadOnlyCollection<UserValue> Wraps List<UserValue> oder beide sind UserValues).

+0

Das wird eine neue Instanz des 'ReadOnlyCollection ' Wrappers jedes Mal erstellen, wenn auf die Eigenschaft zugegriffen wird - wahrscheinlich nicht ideal. –

+0

Es ist wahr, dass es nicht "ideal" ist, aber in diesem Fall beantwortet es die Frage und bringt den Fragesteller auf den Weg. Sie könnten .AsReadOnly wie die anderen vorgeschlagen haben, aber wenn Sie es dekompilieren, sehen Sie, dass es dies tut: return new ReadOnlyCollection ((IList ) this) ;. Die "beste" Lösung (je nach den Bedürfnissen der Person) wäre, ein Mitglied zu erstellen, das die readonly-Sammlung hält, und das zurückzugeben ... aber das schien über den Rahmen der Frage hinauszugehen, die ein Casting-Problem war. – Gjeltema

+0

Ich hatte gerade Zeit, den Code oben zu versuchen und es wird auch nicht kompilieren. – Debbie

3

Sie bekommen die Fehler bei der Kompilierung, weil ein List<UserValue>nicht ein ReadOnlyCollection<UserValue> ist, noch ist es zu, dass implizit konvertierbar. (Ich nehme an, Sie ReadOnlyCollection<UserValue> gemeint statt ReadOnlyCollection<UserValues> durch die Art und Weise?)

Es ist wahrscheinlich einfachste List<T>.AsReadOnly zu verwenden - aber man könnte genauso gut es nur einmal erstellen:

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; } } 
} 

Die ReadOnlyCollection<T> wirklich nur eine Ansicht ist - Änderungen an der zugrunde liegenden Sammlung werden daher in der Ansicht sichtbar.

+0

Hallo Jon. Nein, ich habe wirklich "UserValues" mit einem s gemeint. Mein Vorgesetzter hat mir die Code-Stubs gegeben und ich soll sie ausfüllen, ohne die Methodensignatur zu ändern. Dies wäre viel einfacher, wenn ich die Signatur ändern könnte, um die Variable anzupassen. – Debbie

+0

@Debbie: Nun, der Code, den Sie in der Frage geschrieben haben, macht wenig Sinn. Bist du sicher, dass es kein Tippfehler ist? Ich schlage vor, Sie fragen Ihren Vorgesetzten. Es macht Sinn, dass eine 'UserValues'-Klasse eine Sammlung von' UserValue'-Objekten hat, jedoch keine Sammlung von 'UserValues'-Objekten. –

2

_Values ist ein List<UserValue>, kein ReadOnlyCollection<UserValue> (sie sind nicht verwandt, so weit wie der Compiler weiß), so dass Sie nicht _Values direkt zurückkehren können. Sie können entweder einen ReadOnlyCollection<T> aus Ihrer Liste erstellen und zurückgeben, wie:

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

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

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

... oder, wenn Sie gerade für eine Nur-Lese-Art und Weise der Zugriff auf Ihre Sammlung suchen und brauchen keine ReadOnlyCollection<UserValue> Insbesondere können Sie Ihre Eigenschaft ändern, um eine schreibgeschützte Schnittstelle zurückzugeben, die List<T> implementiert, und Ihre Anwendung könnte stattdessen diese verwenden. .NET 4.5 einig schreibgeschützte Auflistung Schnittstellen eingeführt, die große für diese Art der Sache ist:

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

Leider habe ich keinen Zugang zu .net 4.5. Mein Visual Studio ist 2008. Bis jetzt wird nichts, was hier erwähnt wird, mit der Version von Visual Studios funktionieren, die ich habe. Kann jemand bitte ihre Antworten von .net 4.5 auf .net 3.5 "dumb down" machen? – Debbie

+0

Mein Code kompiliert Targeting .Net 3.5. Darüber hinaus wird die .AsReadOnly(), die Jeremy und Jon empfohlen haben, seit .Net 2.0 unterstützt, so dass auch sie kompiliert werden (http://msdn.microsoft.com/en-us/library/e78dcd75(v=vs.90)) .aspx). Das Problem besteht darin, dass Sie die readonly-Sammlung 'UserValues' benötigen, die eine 'UserValue'-Sammlungsklasse umschließt. Bitte geben Sie weitere Informationen an, die ich in meiner Antwort zur Beantwortung Ihrer Frage angegeben habe. – Gjeltema

Verwandte Themen