3

我正在尝试使用 LINQ To Objects 创建一个查询,该查询将为我提供文件,这些文件由文件名索引,其二进制数据的值映射为byte[].

但是我找不到一个“整洁”的方法来做到这一点。我希望得到类似Dictionary<T,K>输出的东西。

这是我到目前为止所拥有的。示例 delimFileNames="1.jpg|2.jpg"

//Extract filenames from filename string
//and read file binary from file
//select result into a filename indexed collection
var result = from f in delimFileNames.Split(Constants.DDS_FILENAME_SEPARATOR)
            let filePath = Path.Combine(ddsClient.WorkingDirectory, f)
            let fileData = File.ReadAllBytes(filePath)
            select new KeyValuePair<string, byte[]>(f, fileData);

return result.ToDictionary(kvp => kvp.Key, kvp=> kvp.Value);

主要的问题是为什么我不能使用无参数的 ToDictionary() 或直接转换。任何改进上述内容的建议或替代方案都值得赞赏。

4

3 回答 3

5

ToDictionary()KeyValuePair 必须有一个特殊情况 - 当然,您可以将其添加为您自己的扩展方法:

public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(
     IEnumerable<KeyValuePair<TKey, TValue>> source)
{
    return source.ToDictionary(kvp => kvp.Key, kvp=> kvp.Value);
}

如果没有该扩展方法,您可以这样做:

var result = from f in delimFileNames.Split(Constants.DDS_FILENAME_SEPARATOR)
                                     .ToDictionary(f => f,
          // Outdented to avoid scrolling
          f => File.ReadAllBytes(Path.Combine(ddsClient.WorkingDirectory, f));

基本上,查询表达式允许您执行所有时髦的“let”操作,但会强制您select在最后使用 a,这会使您将两个不同的值(键和字节数组)传播到两个属性中。

于 2009-09-10T13:57:00.563 回答
2

“主要的问题是为什么我不能使用无参数的 ToDictionary() [...]”

因为ToDictionary方法需要知道什么是key,什么是value。微软本可以为这种特殊情况创造一个重载,但没有,因为我想好处不是很大。但是没有什么能阻止您创建自己的扩展方法来做到这一点。

“[...] 或直接演员。”

因为您的 Linq 查询返回的IEnumerable<KeyValuePair<TKey, TValue>>不是Dictionary<TKey, TValue>. 它允许您枚举键/值对,但不允许通过键快速查找。

请注意,Dictionary<TKey, TValue>IS 是一个IEnumerable<KeyValuePair<TKey, TValue>>虽然(它实现了该接口),这意味着您可以像使用 Linq 查询一样遍历键/值对,但底层类型是字典,因此您可以通过键快速查找.

于 2009-09-10T14:10:17.913 回答
1

您不需要使用KeyValuePair<,>,而是可以使用匿名类型,它允许您使用比Keyand更具描述性的名称Value

var files =
    from fileName in delimFileNames.Split(Constants.DDS_FILENAME_SEPARATOR)
    let filePath = Path.Combine(ddsClient.WorkingDirectory, fileName)
    select new
    {
        Path = filePath,
        Data = File.ReadAllBytes(filePath)
    };

return files.ToDictionary(file => file.Path, file => file.Data);
于 2009-09-10T15:09:40.080 回答