2013-05-05 40 views
5

Mam następujące zapieczętowane klasy. Próbuję zwrócić listę jako ReadOnlyCollection. Próbowałem kilku rzeczy, ale nie rozumiem tego. Więc jak mogę zwrócić lub rzucić listę do kolekcji tylko do odczytu?Dlaczego otrzymuję komunikat o błędzie: "nie można niejawnie przekonwertować typu System.Collections.Generic.List"

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

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

Klasa 'Lista ' 'object' został jako klasy bazowej. Klasa 'ReadOnlyCollection ' nie jest zatem klasą podstawową, a ponieważ nie zdefiniowano żadnych niejawnych operatorów, nie można po prostu przekonwertować tych dwóch klas w ten sposób. Jeśli chcesz utworzyć nową wartość 'ReadOnlyCollection <>', użyj '_Values.AsReadOnly()'. Jeśli używasz najnowszej wersji .NET (4.5, VS2012), możesz zmienić typ właściwości na interfejs 'IReadOnlyList '. Ponieważ 'List <>' implementuje 'IReadOnlyList <>', nie wymaga to rzutowania. To nie jest tak bezpieczne (jeśli nie ufasz konsumentom swojej klasy). –

+0

Zdeterminowany konsument mógłby użyć odbicia, aby uzyskać obraz "IList " owinięty przez 'ReadOnlyCollection ' ', nie ma zbyt wiele rzeczy, które możesz zrobić, aby powstrzymać kogoś przed wprowadzeniem w błąd w twoich zajęciach, jeśli naprawdę, naprawdę chcą . Sądzę, że jeśli są * zdeterminowani złamać rzeczy, znajdą sposób, więc nie warto martwić się zbytnio. –

+0

Próbowałem robić _Values.AsReadOnly() jak wspomniano Jeppe i uzyskać dokładnie ten sam błąd kompilatora. Używam tylko vs2008, więc nie mam dostępu do interfejsu, o którym wspomniał. – Debbie

Odpowiedz

4

Spróbuj:

return new ReadOnlyCollection<UserValue>(_Values); 

Edit:

Biorąc pod uwagę to, co pan powiedział Jon, Twój kod nie ma sensu. Twój numer get odwołuje się do typu List<UserValue>, ale chcesz go przekonwertować na typ ReadOnlyCollection<UserValues>, który nie może być zrobiony - to 2 kolekcje 2 różnych typów.

Potrzebujemy więcej informacji, aby pomóc Ci w udzieleniu odpowiedzi na to pytanie. Czy chcesz, aby Twoja klasa UserValues zwróciła kolekcję typów UserValues lub kolekcję typów UserValue? Twój kod implikuje UserValue, ale twoje komentarze na bieżąco podają UserValues. Czy jesteś pewien, że twój przełożony nie popełnił literówki?

Jeśli nie, trzeba jakąś kolekcję wewnętrznego tak:

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

A potem wrócić, że w składni I (lub inni, którzy odpowiedzieli - wszystkie odpowiedzi podane są ważne do konwersji Wyświetl listę do ReadOnlyCollection).

Zauważ, że mój kod kompiluje kierowanie .Net 3.5, zakładając, że typy są kompatybilne (co oznacza ReadOnlyCollection<UserValue> zawija List<UserValue> lub oba są UserValues).

+0

Spowoduje to utworzenie nowej instancji opakowania 'ReadOnlyCollection ' za każdym razem, gdy dostęp do właściwości - prawdopodobnie nie jest idealny. –

+0

To prawda, że ​​nie jest "idealny", ale w tym przypadku odpowiada na pytanie i stawia pytającego w drodze. Możesz to zrobić .AsReadOnly, jak sugerowali inni, ale jeśli go zarchiwizujesz, zobaczysz, że robi to: zwróć nową ReadOnlyCollection ((IList )); "Najlepszym" rozwiązaniem (w zależności od potrzeb danej osoby) byłoby stworzenie członka, który przechowuje kolekcję tylko do odczytu, i zwróci to ... ale wydawało się to poza zakresem pytania, które było problemem z rzucaniem. – Gjeltema

+0

Po prostu miałem czas, aby wypróbować powyższy kod, który również nie zostanie skompilowany. – Debbie

3

Stajesz się błąd kompilacji, ponieważ List<UserValue> jest nieReadOnlyCollection<UserValue>, ani nie jest niejawnie zamienny do tego. (Zakładam, że masz na myśli ReadOnlyCollection<UserValue> zamiast ReadOnlyCollection<UserValues> przy okazji?)

To chyba najprostsze w użyciu List<T>.AsReadOnly - ale równie dobrze można utworzyć tylko raz:

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

ReadOnlyCollection<T> naprawdę jest tylko widok - więc zmiany w podstawowej kolekcji będą widoczne w widoku.

+0

Cześć Jon. Nie, naprawdę miałem na myśli "UserValues" z s. Mój przełożony podał mi kody kodu i mam je wypełnić bez zmiany podpisu metody. Byłoby o wiele łatwiej, gdybym mógł zmienić podpis, by pasował do zmiennej. – Debbie

+0

@Debbie: Kod, który napisałeś w pytaniu, nie ma większego sensu. Jesteś pewien, że to nie jest literówka? Sugeruję, aby zapytać swojego przełożonego. Ma sens dla klasy 'UserValues', aby mieć kolekcję obiektów' UserValue', ale nie dla kolekcji zbioru 'UserValues'. –

2

_Values jest List<UserValue>, a nie ReadOnlyCollection<UserValue> (nie są one związane, o ile kompilator wie), więc nie można powrócić _Values bezpośrednio. Można też stworzyć ReadOnlyCollection<T> z listy i wrócić, że podobnie jak:

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

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

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

... lub, jeśli jesteś po prostu patrząc na tylko do odczytu sposób uzyskiwania dostępu do swojej kolekcji i nie potrzebują ReadOnlyCollection<UserValue> w szczególności, możesz zmienić swoją własność, aby zwrócić interfejs tylko do odczytu, który implementuje List<T>, a Twoja aplikacja może zamiast tego użyć tego. .NET 4.5 wprowadzono kilka interfejsów tylko do odczytu poboru, które są wielką dla tego rodzaju rzeczy:

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

Niestety, nie mam dostępu do .net 4.5. Moje studio wizualne to 2008. Jak dotąd, żadne wspomniane tu informacje nie będą działać z wersją Visual Studios, którą mam. Czy ktoś może "głupie" odpowiedzi z .net 4.5 na .net 3.5, proszę? – Debbie

+0

Mój kod kompiluje kierowanie .Net 3.5. Ponadto .AsReadOnly(), które Jeremy i Jon polecili, jest obsługiwane od .Net 2.0, więc ich również się skompiluje (http://msdn.microsoft.com/en-us/library/e78dcd75(v=vs.90) .aspx). Problem polega na tym, że potrzebujesz tylko kolekcji "UserValues' readonly owijającej klasę kolekcji" UserValue ". Podaj więcej informacji, jak zaznaczono w mojej odpowiedzi, aby pomóc nam odpowiedzieć na twoje pytanie. – Gjeltema

Powiązane problemy