我正在尝试使用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()或直接演员。任何改善上述内容的建议或替代方案均值得赞赏。
答案 0 :(得分: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
,这会使您传播两个不同的值(键和字节数组)分为两个属性。
答案 1 :(得分:2)
“主要问题是为什么我不能使用无参数的ToDictionary()[...]”
因为ToDictionary
方法需要知道什么是密钥以及值是什么。微软可能已经为这个特殊情况创造了一个过载,但没有,因为我想这个好处不是很大。但是没有什么可以阻止你创建自己的扩展方法,而这正好就是这样。
“[...]或直接演员。”
因为您的Linq查询返回的IEnumerable<KeyValuePair<TKey, TValue>>
不是Dictionary<TKey, TValue>
。它允许您枚举键/值对,但不允许按键快速查找。
请注意,Dictionary<TKey, TValue>
是IEnumerable<KeyValuePair<TKey, TValue>>
虽然(它实现了该接口),这意味着您可以像使用Linq查询一样迭代键/值对,但是底层type是一个Dictionary,因此您可以通过键快速查找。
答案 2 :(得分:1)
您不需要使用KeyValuePair<,>
,而是可以使用匿名类型,允许您使用比Key
和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);