2017-01-25 10 views
0

У меня есть список массив строк, и я хотел бы сделать обе коллекции доступными только для чтения.IList <IList<T>> to IReadonlyCollection <IReadonlyCollection <T>>

Так что у меня этот код:

public XmlPatternTree(IList<string> nodeNames, IList<IList<string>> attributeNames, 
     IList<IList<string>> attributeValues) : this() 
    { 
     NodeNames = new ReadOnlyCollection<string>(nodeNames); 
     AttributeNames = new ReadOnlyCollection<ReadOnlyCollection<string>>(); 
     AttributeValues = attributeValues; 
     Depth = NodeNames.Count; 
    } 

Моя проблема заключается в том, что AttributeNames и AttributeValues ​​назначения вызывает ошибку компиляции, то кажется, что я могу создать ReadOnlyCollection из ReadOnlyCollection из не только для чтения коллекции не-ReadOnly объекты.

Есть ли что-то, что я могу сделать, кроме циклов по всем значениям и добавить их в список?

Благодаря

ответ

2

Если вы измените тип от IList<string> просто List<string>, то это должно работать:

attributeNames.Select((x) => x.AsReadOnly()).ToList().AsReadOnly(); 

Если вы не можете изменить свой метод подписи (т.е. вы имеют держать IList<string>), то вы можете сделать это:

attributeNames.Select((x) => x.ToList().AsReadOnly()).ToList().AsReadOnly(); 
1

Если версия t он .net framework больше 4.0. Общая версия List<> реализует интерфейс IReadOnlyCollection<>. Если вам удобнее, вы можете изменить свою подпись от IList<ILIst<>> до List<List<>> и должны работать нормально.

AttributeNames = attributeNames; 
AttributeValues = attributeValues; 
1

Просто записка о ковариации IReadOnlyList<out T> типа (аналогично ответу Васил oreshenski в).

Если вы решили:

public XmlPatternTree(IReadOnlyList<string> nodeNames, 
    IReadOnlyList<IReadOnlyList<string>> attributeNames, 
    IReadOnlyList<IReadOnlyList<string>> attributeValues) : this() 
{ 
    NodeNames = nodeNames; 
    AttributeNames = attributeNames; 
    AttributeValues = attributeValues; 
} 

public IReadOnlyList<string> NodeNames { get; private set; } 
public IReadOnlyList<IReadOnlyList<string>> AttributeNames { get; private set; } 
public IReadOnlyList<IReadOnlyList<string>> AttributeValues { get; private set; } 
public int Depth => NodeNames.Count; 

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

var nn = new List<string>(); 
var an = new List<string[]>(); 
var av = new List<string[]>(); 
// populate 'nn', 'an', and 'av' 

// the following compiles with no wrapper class: 
var tree = new XmlPatternTree(nn, an, av); 

Конечно, люди могут передавать интерфейсы обратно к фактическим типам, например List<string[]>, и изменять коллекции без использования отражения, если они предполагают, что тип действительно является списком массивов. Тем не менее, это было бы довольно злокачественным, поэтому вы могли бы предположить, что это не проблема, если только «хорошие» люди используют ваш класс

PS! То, что я сказал и закодированное выше с IReadOnlyList<out T>, может быть также сделано с IReadOnlyCollection<out T>, так как оно является ковариантным («out»). У вас просто не будет доступа индексатора к свойствам (например, var name = tree.AttrbuteNames[idx1][idx2]). Но тогда вы можете использовать HashSet<> и аналогичные, которые не являются IReadOnlyList<>.