我的字典值是一个列表。我需要阅读每个列表以提取字段。但是在foreach循环中得到以下错误
无法转换类型
System.Collections.Generic.List<UserQuery.Employee>
来UserQuery.Employee
如果我在var iValue的注释行中使用firstorDefault,它会起作用。但是我会在我正在阅读的字典中检查多条记录(尽管在这个例子中,我硬编码为1,以测试我的代码)。
void Main()
{
var svalue =1;
List<Employee> emplist = new List<Employee>()
{
new Employee{ EID=10, Ename="John"},
new Employee{ EID=11, Ename="Adam"},
new Employee{ EID=12, Ename="Ram"}
};
List<Employee> emplist1 = new List<Employee>()
{
new Employee{ EID=1, Ename="Jo"},
new Employee{ EID=1, Ename="Ad"},
new Employee{ EID=1, Ename="Ra"}
};
var dict1 = new Dictionary<int, List<Employee>>();
dict1.Add(1, emplist);
dict1.Add(2, emplist1);
//var ivalue = dict1.FirstOrDefault(x => x.Key == svalue).Value.ToList();
var ivalue = dict1.Where(kvp => dict1.ContainsKey(1)).Select(x => x.Value);
Console.WriteLine(ivalue);
foreach (Employee emp in ivalue)
{
Console.WriteLine(emp.EID);
}
}
class Employee
{
public int EID { get; set;}
public string Ename {get; set;}
}
答案 0 :(得分:2)
您当前的代码
var ivalue = dict1
.Where(kvp => dict1.ContainsKey(1)) //TODO: Very strange condition: check it
.Select(x => x.Value);
返回IEnumerable<List<Employee>>
作为结果(ivalue
)。由于您只需要IEnumerable<Employee>
,因此您必须展平结果:
var ivalue = dict1
.Where(kvp => dict1.ContainsKey(1))
.SelectMany(kvp => kvp.Value); // kvp: we still have key-value pair
然而,这不是我们处理字典的方式;你可能正在寻找这样的东西(让我们保留一些Linq: - .Select(emp => emp.EID)
):
if (dict1.TryGetValue(1, out var ivalue)) // do we have corresponding value?
Console.WriteLine(String.Join(Environment.NewLine, ivalue // if yes, print them out
.Select(emp => emp.EID)));
答案 1 :(得分:1)
这不是你通常使用词典的方式。你想做的是这样的:
if (dict1.ContainsKey(1)) // if the dictionary contains the key
{
var ivalue = dict1[1]; // get the value of that key
}
有了这个,您正在使用最有效的方式来搜索字典。所以你应该这样做:
var dict1 = new Dictionary<int, List<Employee>>();
dict1.Add(1, emplist);
dict1.Add(2, emplist1);
if (dict1.ContainsKey(1))
{
var ivalue = dict1[1];
Console.WriteLine(ivalue); // this will print System.Collections.Generic.List<Employee>
foreach (Employee emp in ivalue)
{
Console.WriteLine(emp.EID);
}
}
另一种选择是使用TryGetValue
:
var dict1 = new Dictionary<int, List<Employee>>();
dict1.Add(1, emplist);
dict1.Add(2, emplist1);
List<Employee> ivalue = null;
if (dict1.TryGetValue(1, out ivalue))
{
Console.WriteLine(ivalue); // this will print System.Collections.Generic.List<Employee>
foreach (Employee emp in ivalue)
{
Console.WriteLine(emp.EID);
}
}
答案 2 :(得分:0)
Where收到两次KeyValuePair,当然对KeyValuePair都返回true,因为你总是问同样的问题。字典是否包含密钥== 1?是。因此,Where的返回是两个List<Employee>
元素的可枚举,无法转换为单个通用列表。
var ivalue = dict1.FirstOrDefault(kvp => dict1.ContainsKey(1));
if(ivalue.Value != null)
foreach (Employee emp in ivalue.Value)
Console.WriteLine(emp.EID);
当然,正如评论中所指出的,Linq的这种使用是没有根据的,因为你的代码可以简化为
List<Employee> empList;
// Try directly to get the List<Employee> that match the Key
// if found you have the empList initialized with the matching list
// otherwise TryGetValue returns false.
if(dict.TryGetValue(1, out empList))
foreach (Employee emp in empList)
Console.WriteLine(emp.EID);
答案 3 :(得分:0)
执行var ivalue = dict1.Where(kvp => dict1.ContainsKey(1)).Select(x => x.Value);
时,您使用Where
方法过滤列表,然后使用Select
选择所有值。
您获得该异常是正常的,因为Select会为您提供一个列表,而不是一个条目。您应该foreach
列出该列表,或使用FirstOrDefault
并获得1个单值。
foreach (var value in dict1.Where(kvp => dict1.ContainsKey(1)).Select(x => x.Value))
{
// ...
}
或者
var ivalue = dict1.Where(kvp => dict1.ContainsKey(1)).Select(x => x.Value).FirstOrDefault();
答案 4 :(得分:0)
var ivalue = dict1.Where(kvp => dict1.ContainsKey(1)).Select(x => x.Value);
将返回带有List类型元素的'IEnumerable'。 所以你需要两个嵌套的foreach循环:
'outer'用于遍历从Dictionary中检索到的所有列表,'inner'用于迭代当前List中的所有员工。
答案 5 :(得分:0)
我不认为你的意思是:dict1.ContainsKey(1))
我想你是在这之后:
var ivalue = dict1.FirstOrDefault(d =>d.Key==1 ).Value ;
if (ivalue!=null)
foreach (Employee emp in ivalue)
{
Console.WriteLine(emp.EID);
}
请注意:
var ivalue = dict1.Where(kvp => dict1.ContainsKey(1)).Select(x => x.Value);
检查字典是否为1作为键,但不会在结果中考虑该键。