的IList <IList的<T>&GT;到IReadonlyCollection <ireadonlycollection <t>&gt;

时间:2017-01-25 15:49:44

标签: c# .net c#-4.0 readonly readonly-collection

我有一个字符串数组列表,我想将这两个集合设为只读。

所以我有这段代码:

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。

除了循环遍历所有值并将其添加到列表中之外,我还能做些什么吗?

由于

3 个答案:

答案 0 :(得分:2)

如果您将类型从IList<string>更改为List<string>,那么这应该有效:

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

如果您无法修改方法签名(即 保留IList<string>),那么您可以这样做:

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

答案 1 :(得分:1)

如果.net框架的版本大于4.0,则List<>的通用版本实现IReadOnlyCollection<>接口。 如果对您来说更方便,您可以将签名从IList<ILIst<>>更改为List<List<>>,并且应该可以正常使用。

 AttributeNames = attributeNames;
 AttributeValues = attributeValues;

答案 2 :(得分:1)

关于IReadOnlyList<out T>类型的协方差的注释(类似于vasil 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[]>,并在不使用反射的情况下修改集合,如果他们猜测类型实际上是数组列表。然而,这将是非常恶性的,所以你可以假设它只是&#34;好&#34;人们使用你的班级

PS!我在上面用IReadOnlyList<out T>编写和编码的内容也可以用IReadOnlyCollection<out T>完成,因为它是协变的(&#34; out&#34;)。您不会在属性上拥有索引器访问权限(例如var name = tree.AttrbuteNames[idx1][idx2])。但是,您可以使用HashSet<>和类似的IReadOnlyList<>