IList<IList<T>> 到 IReadonlyCollection<IReadonlyCollection<T>>
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。
除了遍历所有值并将它们添加到列表中之外,我还能做些什么吗?
谢谢
如果您将类型从 IList<string>
更改为 List<string>
,那么这应该有效:
attributeNames.Select((x) => x.AsReadOnly()).ToList().AsReadOnly();
如果你不能修改你的方法签名(即你有来保留IList<string>
),那么你可以这样做:
attributeNames.Select((x) => x.ToList().AsReadOnly()).ToList().AsReadOnly();
如果 .net 框架的版本高于 4.0,List<>
的通用版本将实现 IReadOnlyCollection<>
接口。
如果您更方便,可以将签名从 IList<ILIst<>>
更改为 List<List<>>
,应该可以正常工作。
AttributeNames = attributeNames;
AttributeValues = attributeValues;
只是关于 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;
在你的 class 中,那么提到的协方差意味着你可以使用引用转换, 而不是在另一个 class 内进行任何包装,如:
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[]>
,并且在不使用反射的情况下修改集合,如果他们猜测类型确实是数组列表的话。但是,这将是非常有害的,因此您可以认为只要 "good" 人使用您的 class
就没有问题
PS!我在上面用 IReadOnlyList<out T>
所说和编码的内容也可以用 IReadOnlyCollection<out T>
完成,因为它也是协变的(“out
”)。您只是没有索引器访问属性(例如 var name = tree.AttrbuteNames[idx1][idx2]
)。但是你可以使用 HashSet<>
和类似的东西,它们不是 IReadOnlyList<>
.
我有一个字符串数组列表,我想将这两个集合设为只读。
所以我有这个代码:
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。
除了遍历所有值并将它们添加到列表中之外,我还能做些什么吗?
谢谢
如果您将类型从 IList<string>
更改为 List<string>
,那么这应该有效:
attributeNames.Select((x) => x.AsReadOnly()).ToList().AsReadOnly();
如果你不能修改你的方法签名(即你有来保留IList<string>
),那么你可以这样做:
attributeNames.Select((x) => x.ToList().AsReadOnly()).ToList().AsReadOnly();
如果 .net 框架的版本高于 4.0,List<>
的通用版本将实现 IReadOnlyCollection<>
接口。
如果您更方便,可以将签名从 IList<ILIst<>>
更改为 List<List<>>
,应该可以正常工作。
AttributeNames = attributeNames;
AttributeValues = attributeValues;
只是关于 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;
在你的 class 中,那么提到的协方差意味着你可以使用引用转换, 而不是在另一个 class 内进行任何包装,如:
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[]>
,并且在不使用反射的情况下修改集合,如果他们猜测类型确实是数组列表的话。但是,这将是非常有害的,因此您可以认为只要 "good" 人使用您的 class
PS!我在上面用 IReadOnlyList<out T>
所说和编码的内容也可以用 IReadOnlyCollection<out T>
完成,因为它也是协变的(“out
”)。您只是没有索引器访问属性(例如 var name = tree.AttrbuteNames[idx1][idx2]
)。但是你可以使用 HashSet<>
和类似的东西,它们不是 IReadOnlyList<>
.