2013-05-05 4 views
5

У меня есть следующий герметичный класс. Я пытаюсь вернуть список как ReadOnlyCollection. Пробовал пару вещей, но я не понимаю этого. Итак, как мне вернуть или передать список в коллекцию readonly?Почему я получаю ошибку: «не может неявно преобразовать тип System.Collections.Generic.List»

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

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

Класс 'Список ' 'имеет object' в качестве базового класса. Поэтому класс 'ReadOnlyCollection ' не является базовым классом, и поскольку не определены неявные операторы, вы не можете просто преобразовать эти два класса. Если вы хотите создать новый 'ReadOnlyCollection <>', используйте '_Values.AsReadOnly()'. Если вы используете новейшую версию .NET (4.5, VS2012), вы можете изменить тип свойства на интерфейс 'IReadOnlyList '. Поскольку 'List <>' реализует 'IReadOnlyList <>', это не требует никакого броска. Это не так безопасно (если вы не доверяете потребителям своего класса). –

+0

Определенный потребитель может использовать отражение, чтобы получить в 'IList ', обернутый 'ReadOnlyCollection ' тоже, хотя - вы не можете сделать, чтобы кто-то не возился с внутренностями ваших классов, если они действительно, действительно хотят , Я полагаю, что если они * решили * сломать вещи, они найдут способ, поэтому не стоит слишком беспокоиться. –

+0

Я пробовал делать _Values.AsReadOnly(), как упоминал Jeppe, и получить ту же самую ошибку компилятора. И я использую только vs2008, поэтому у меня нет доступа к упомянутому интерфейсу. – Debbie

ответ

4

Try:

return new ReadOnlyCollection<UserValue>(_Values); 

Edit:

Учитывая то, что вы сказали Джону, что ваш код не имеет смысла. Ваш get ссылается на тип List<UserValue>, но вы хотите преобразовать его в тип ReadOnlyCollection<UserValues>, который не может быть выполнен - ​​это 2 коллекции из 2 разных типов.

Нам нужна дополнительная информация, которая поможет вам ответить на этот вопрос. Вы хотите, чтобы ваш класс UserValues возвращал коллекцию из UserValues типов, или коллекцию из UserValue? Ваш код подразумевает UserValue, но следующее по комментариям: UserValues. Вы уверены, что ваш руководитель не сделал опечатку?

Если нет, то вы будете нуждаться в какой-то внутренний сбор примерно так:

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

А потом вернуться, что в синтаксисе, что я (или другие, которые ответили - все ответы, данные действительны для преобразования Список ReadOnlyCollection).

Обратите внимание, что мой код компилирует таргетинг .Net 3.5, предполагая, что типы совместимы (то есть ReadOnlyCollection<UserValue> обертывает List<UserValue> или оба являются UserValues).

+0

Это создаст новый экземпляр оболочки 'ReadOnlyCollection ' каждый раз, когда будет доступно свойство - вероятно, не идеально. –

+0

Это правда, что это не «идеальный», но в этом случае он отвечает на вопрос и задает вопрос на своем пути. Вы могли бы сделать .AsReadOnly, как предложили другие, но если вы декомпилируете его, вы увидите, что он делает это: return new ReadOnlyCollection ((IList ) this) ;. «Лучшее» решение (в зависимости от потребностей человека) заключалось бы в создании члена, который содержит коллекцию только для чтения, и возвращает это ... но это, казалось, выходит за рамки вопроса, что было проблемой кастинга. – Gjeltema

+0

Я просто успел попробовать код выше, и он тоже не будет скомпилирован. – Debbie

3

Вы получаете ошибку во время компиляции, потому что List<UserValue>является неReadOnlyCollection<UserValue>, ни неявно конвертируются в этом. (Я предполагаю, что вы имели в виду ReadOnlyCollection<UserValue> вместо ReadOnlyCollection<UserValues>, кстати?)

Это, вероятно, проще всего использовать List<T>.AsReadOnly - но вы можете также создать только один раз:

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> действительно просто вид - поэтому изменения в базовой коллекции будут видны через представление.

+0

Привет, Джон. Нет, я действительно имел в виду «UserValues» с s. Мой руководитель дал мне заглушки кода, и я должен заполнить их, не меняя подписи метода. Это было бы намного проще, если бы я мог изменить подпись для соответствия переменной. – Debbie

+0

@Debbie: Ну код, который вы написали в вопросе, имеет мало смысла. Вы уверены, что это не опечатка? Я предлагаю вам спросить своего руководителя. Для класса 'UserValues' имеет смысл иметь коллекцию объектов UserValue, но не для того, чтобы иметь коллекцию объектов UserValues. –

2

_Values является List<UserValue>, не ReadOnlyCollection<UserValue> (они не связаны, насколько компилятор знает), так что вы не можете вернуть _Values непосредственно. Вы можете либо создать ReadOnlyCollection<T> из списка и возврата, которые, как:

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

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

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

... или, если вы просто ищете способ только для чтения доступа к вашей коллекции и не нуждаются в ReadOnlyCollection<UserValue> объект, вы можете изменить свое свойство, чтобы вернуть интерфейс только для чтения, который реализует List<T>, и вместо этого ваше приложение может использовать это. .NET 4.5 введены некоторые только для чтения интерфейсы сбора, которые большой для такого рода вещи:

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

К сожалению, у меня нет доступа к .net 4.5. Моя визуальная студия - 2008. До сих пор ничто не упоминается здесь, будет работать с версией Visual Studios, которую я имею. Может ли кто-нибудь «отбросить» свои ответы от .net 4.5 до .net 3.5, пожалуйста? – Debbie

+0

Мой код компилирует таргетинг. Net 3.5. Кроме того, рекомендуется использовать метод .AsReadOnly(), рекомендованный Джереми и Джоном, поддерживаемый с .Net 2.0, поэтому их компиляция тоже (http://msdn.microsoft.com/en-us/library/e78dcd75(v=vs.90) .aspx). Проблема заключается в том, что вы нуждаетесь в сборнике 'UserValues' только для чтения, в котором используется класс коллекции UserValue. Пожалуйста, предоставьте дополнительную информацию, как я отметил в своем ответе, чтобы помочь нам ответить на ваш вопрос. – Gjeltema

Смежные вопросы