2

我在方法中有以下字典:

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   

我不知道该怎么办。

4

3 回答 3

3

简短的回答:您不能从函数返回匿名类型。

长答案:您的字典的值类型是匿名的{BaseHours, OvertimeHours},它不能从函数返回或作为参数传递(作为对象除外,但除非您经历了反思的麻烦,否则没有任何好处)。要么在其中定义一个类/结构BaseHoursOvertimeHours要么使用一个元组。前者可能稍微好一些,因为您可以保留名称BaseHoursOvertimeHours; 使用一个元组,您可以得到Value1and Value2

于 2012-08-14T18:24:30.650 回答
2

如果您使用的是 C# 4.0,则可以通过动态类型返回匿名。所以你的方法签名看起来像这样

protected IDictionary<Tuple<int,int,string>, dynamic> OvertimereportData(HarvestTargetTimeRangeUTC ranges)

并且通过动态对象可以找到运行时的属性。

希望这会帮助你。

于 2012-08-14T18:34:20.263 回答
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>(...)

但是,第二个将是一个问题。字典中的值是匿名类型:您返回 anew { }而不为该值指定具体类型名称。通常,这将使您无法将该字典用作返回值或参数。(可以使用一些看起来很奇怪的通用技术来完成,但我不推荐它。)

那么,您需要做的第一件事就是制作一个具体的类型来保存您的值,例如

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>或任何东西,但是生成的泛型类型会很快变得笨拙。)

于 2012-08-14T18:29:12.043 回答