1

I have a list of string array and I would like to make both collection read-only.

So I have this code:

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

My issue is that AttributeNames and AttributeValues assignments causes a compilation error, it seems that I can create a ReadonlyCollection of ReadonlyCollection from a non-readonly collection of non-readonly objects.

Is there something I can do other than looping over all the values and add them in the list ?

Thanks

4

3 回答 3

3

如果您将类型从更改IList<string>为 just List<string>,则应该可以:

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

如果你不能修改你的方法签名(即你必须保持IList<string>),那么你可以这样做:

attributeNames.Select((x) => x.ToList().AsReadOnly()).ToList().AsReadOnly();
于 2017-01-25T15:52:56.027 回答
1

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

 AttributeNames = attributeNames;
 AttributeValues = attributeValues;
于 2017-01-25T17:11:56.760 回答
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[]>,并在不使用反射的情况下修改集合,如果他们猜测该类型确实是数组列表。但是,那将是非常恶性的,因此您可以假设只有“好”的人使用您的课程没有问题

PS!我上面所说和编码的内容IReadOnlyList<out T>也可以完成,IReadOnlyCollection<out T>因为它也是协变的(“ out”)。您只是没有对属性(例如var name = tree.AttrbuteNames[idx1][idx2])的索引器访问权限。但是你可以使用HashSet<>and similar which are not IReadOnlyList<>.

于 2017-01-25T18:05:24.307 回答