C# 无法隐式转换类型System.Collections.Generic.Dictionary<;系统元组<;int,int,string>;,匿名类型#1>;

C# 无法隐式转换类型System.Collections.Generic.Dictionary<;系统元组<;int,int,string>;,匿名类型#1>;,c#,linq-to-xml,idictionary,C#,Linq To Xml,Idictionary,我有一个方法中的以下词典: 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.Ancestor

我有一个方法中的以下词典:

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
                    };
         });

我不知道该怎么办。

简单的回答是:不能从函数返回匿名类型


答案很长:您的字典的值类型是匿名的
{BaseHours,OvertimeHours}
,不能从函数返回或作为参数传递(对象除外,但这没有任何好处,除非您考虑到它)。在类/结构中定义
BaseHours
OvertimeHours
,或者使用元组。前者可能稍好一些,因为您可以保留名称
BaseHours
OvertimeHours
;对于元组,当调用
ToDictionary
方法时,只会得到
Value1
Value2
,结果字典的类型与源序列中元素的类型几乎没有关系。它完全由提供给调用的键和值表达式返回的数据类型定义。例如,如果您要呼叫:

xelem.Descendants(plantNS + "Month").ToDictionary(
  k => int.Parse(k.Attribute("Year").Value),
  v => k.Attribute("Year).Value
);
您将得到一个
IDictionary
,因为这是两个表达式返回的结果。要从方法返回该值,只需根据表达式构造正确的类型

你的第一个很简单:

k => new Tuple<int, int, string>(...)
并适当更改Linq查询:

var detail = v.Descendants(plantNS + "Details").First();                
return new HoursContainer
{
    BaseHours = detail.Attribute("BaseHours").Value,
    OvertimeHours = detail.Attribute("OvertimeHours").Value
};
完成此操作后,字典将根据创建时指定的内容类型具有具体类型:

IDictionary

(注意:如果需要,您也可以使用另一个
元组
或其他任何类型,但生成的泛型类型将很快变得难以处理。)

如果您使用的是C#4.0,则可以通过类型返回匿名。所以你的方法签名应该是这样的

protected IDictionary<Tuple<int,int,string>, dynamic> OvertimereportData(HarvestTargetTimeRangeUTC ranges)
受保护的IDictionary OvertimereportData(HarvestTargetTimeRangeUTC范围)
通过动态对象,您可以在运行时找到属性


希望这会对您有所帮助。

从技术上讲,您可以将其返回(如
对象
等),但很难使用它做任何有用的事情:-)@JamesMichaelHare True enough但如何创建方法签名?当我尝试使用受保护的IDictionary OvertimereportData(HarvestTargetTimeRangeUTC ranges)时,仍然会收到一个错误,指出无法使用元组,因为它是静态类型。您确定使用了
元组
,而不仅仅是
元组
?不能实例化非泛型的
元组
——它只有静态方法。您需要指定
元组中的泛型类型。是的,先生。我直接从VS2010剪切并粘贴了该方法。“受保护的IDictionary OvertimereportData(HarvestTargetTimeRangeUTC范围)”我在清理解决方案后使其工作。谢谢你的帮助。不幸的是,无论我使用您的解决方案还是Michael Edenfield的解决方案,最终都会出现相同的错误消息:System.Tuple:静态类型不能用作类型参数
k => new Tuple<int, int, string>(...)
public class HoursContainer 
{
  public string BaseHours { get; set; }
  public string OvertimeHouse { get; set; }
}
var detail = v.Descendants(plantNS + "Details").First();                
return new HoursContainer
{
    BaseHours = detail.Attribute("BaseHours").Value,
    OvertimeHours = detail.Attribute("OvertimeHours").Value
};
protected IDictionary<Tuple<int,int,string>, dynamic> OvertimereportData(HarvestTargetTimeRangeUTC ranges)