Voj*_*ech 15 c# generics collections inheritance
我正在努力实施FilePathCollection.它的项目是简单的文件名(没有路径 - 例如"image.jpg").一旦通过foreach循环使用集合,它应该返回通过连接创建的完整路径baseDirectory.我怎样才能做到这一点?
public class FilePathCollection : List<string>
{
string baseDirectory;
public FilePathCollection(string baseDirectory)
{
this.baseDirectory = baseDirectory;
}
new public System.Collections.IEnumerator GetEnumerator()
{
foreach (string value in this._items) //this does not work because _list is private
yield return baseDirectory + value;
}
}
Run Code Online (Sandbox Code Playgroud)
Mat*_*hen 26
new public IEnumerator GetEnumerator()
{
using(IEnumerator ie = base.GetEnumerator())
while (ie.MoveNext()) {
yield return Path.Combine(baseDirectory, ie.Current);
}
}
Run Code Online (Sandbox Code Playgroud)
Dan*_*ker 12
如果您有C#3,则无需编写特殊类来执行此操作.假设你有一个字符串,如序列List<string>或者string[],任何支持IEnumerable<string>,叫filePathCollection,你可以使用:
var prefixedPaths = filePathCollection.Select(path => baseDirectory + path);
Run Code Online (Sandbox Code Playgroud)
嘿presto - 你现在有一个IEnumerable<string>前缀的路径baseDirectory,所以你可以使用foreach它,等等.我们已经完成了.
本答案的其余部分是更一般的解释,以帮助您(和其他人)发现在其他情况下可以应用的地方.
Select本质上意味着:采取这一系列的项目,对每个项目做一些事情并给我一个包含所有结果的新序列.通过提供一个方法来指定"something",该方法接受与旧序列中存储的相同类型的一个参数,并返回您喜欢的任何类型,这将是新序列的项类型.在这种情况下,我们不会更改项目类型.我们还使用lambda定义了"就地"方法:
path => baseDirectory + path
Run Code Online (Sandbox Code Playgroud)
编译器计算出的源集合的元素类型string,所以path是string-你能想到的path是打一个"循环变量"相同的作用,如果你有写了整个事情了自己.在path我们使用连接时,结果是另一个string,所以新的序列也必须是IEnumerable<string>.这是"类型推断",是这些东西减少你必须编写的代码量的重要部分.
发生的另一个重要事情是"封闭",这是我们如何使我们的lambda不仅依赖于它的"开放"参数path而且依赖于"封闭"参数的技术名称,该参数baseDirectory甚至没有明确地作为一个参数传递给它参数.lambda可以直接到达外部并获得可见的变量.这使得您无需编写构造函数,该构造函数将其baseDirectory作为参数存储并存储在_baseDirectory字段中,以便稍后可以在其他方法中重复使用它.
请注意,新序列的长度始终与传入序列的长度相同.如果要过滤掉项目,请使用Where.如果要延长序列,请使用SelectMany.