我在方法中有以下字典:
var nmDict = xelem.Descendants(plantNS + "Month").ToDictionary(
k => new Tuple<int, int, string>(int.Parse(k.Ancestors(plantNS + "Year").First().Attribute("Year").Value), Int32.Parse(k.Attribute("Month1").Value), k.Ancestors(plantNS + "Report").First().Attribute("Location").Value.ToString()),
v => {
var detail = v.Descendants(plantNS + "Details").First();
return
new
{
BaseHours = detail.Attribute("BaseHours").Value,
OvertimeHours = detail.Attribute("OvertimeHours").Value
};
});
我需要返回nmDict。问题是我无法弄清楚如何标记我的方法签名。我尝试过以下方法:
protected IDictionary<XElement, XElement> OvertimereportData(HarvestTargetTimeRangeUTC ranges)
上面给出了这个错误:
Cannot implicitly convert type System.Collections.Generic.Dictionary<System.Tuple<int,int,string>,AnonymousType#1>' to 'System.Collections.Generic.IDictionary<System.Xml.Linq.XElement,System.Xml.Linq.XElement>'. An explicit conversion exists (are you missing a cast?)
protected IDictionary<Tuple, XElement> OvertimereportData(HarvestTargetTimeRangeUTC ranges)
给了我这个错误:
'System.Tuple': static types cannot be used as type arguments
我不知道该怎么做。
答案 0 :(得分:3)
简短回答:您无法从函数返回匿名类型。
答案很长:你的字典的值类型是匿名{BaseHours, OvertimeHours}
,它不能从函数返回或作为参数传递(除了作为一个对象,但除非你经历反思的麻烦,否则没有任何好处进去)。要么定义一个包含BaseHours
和OvertimeHours
的类/结构,要么使用元组。前者可能略好一些,因为您可以保留名称BaseHours
和OvertimeHours
;使用元组,您只需获得Value1
和Value2
。
答案 1 :(得分:2)
如果您使用的是C#4.0,则可以通过 dynamic 类型返回匿名。所以你的方法签名看起来像这样
protected IDictionary<Tuple<int,int,string>, dynamic> OvertimereportData(HarvestTargetTimeRangeUTC ranges)
通过动态对象,您可以在运行时找到属性。
希望这会对你有所帮助。
答案 2 :(得分:1)
当您调用ToDictionary
方法时,生成的字典的类型与源序列中的元素类型几乎没有关系。它完全由您为调用提供的键和值表达式返回的数据类型定义。例如,如果你打电话:
xelem.Descendants(plantNS + "Month").ToDictionary(
k => int.Parse(k.Attribute("Year").Value),
v => k.Attribute("Year).Value
);
你会得到IDictionary<int, string>
,因为这是你的两个表达式返回的内容。要从方法返回它,您只需要根据表达式构造正确的类型。
你的第一个很容易:
k => new Tuple<int, int, string>(...)
然而,第二个问题将是一个问题。字典中的值是匿名类型:返回new { }
而不指定该值的具体类型名称。通常,这将使您无法将该字典用作返回值或参数。 (可以完成,使用一些非常奇怪的通用技术,但我不推荐它。)
然后,你需要做的第一件事是制作一个具体的类型来保存你的价值观,例如。
public class HoursContainer
{
public string BaseHours { get; set; }
public string OvertimeHouse { get; set; }
}
并适当更改您的Linq查询:
var detail = v.Descendants(plantNS + "Details").First();
return new HoursContainer
{
BaseHours = detail.Attribute("BaseHours").Value,
OvertimeHours = detail.Attribute("OvertimeHours").Value
};
完成此操作后,您的词典将根据您在创建时指定的内容类型具有具体类型:
IDictionary<Tuple<int, int, string>, HoursContainer>
(注意:如果你愿意的话,你也可以使用另一个Tuple<int, int>
或其他任何东西,但是生成的泛型类型会很快变得笨拙。)