无法将源类型转换为目标类型List <keyvaluepair> Linq </keyvaluepair>

时间:2014-01-14 16:38:25

标签: c# linq

我有一个返回列表的List<KeyValuePair<int,string>>方法;但是,我收到了一个错误:

  

无法将源类型System.Collections.Generic.List<{Key:int, Value:string}>转换为目标类型   System.Collections.Generic.KeyValuePair<'int,string'>>

我正在尝试将Linq select语句转换为新列表,但我不明白初始化列表是否存在问题,或者我是如何获取Linq语句中的值的。

以下是方法:

public static List<KeyValuePair<int,string>> GetStatus(int status)
{
   List<KeyValuePair<int,string>> st = SelectList.GetStatuses();
   List<KeyValuePair<int,string>> tp;

   switch(status)
   {
      case (int)Status.Completed:
          tp = st.Where(s => s.Key == (int)Status.Completed ||
                             s.Key == (int)Status.NotValid)
                 .Select(s => new { s.Key, s.Value }).ToList();
      case (int)Status.Open:
          tp = st.Where(s => s.Key == (int)Status.Open ||
                             s.Key == (int)Status.Reviewed)
                 .Select(s => new { s.Key, s.Value }).ToList();
      default:
          break;
   }
   return tp;
}

这是填充列表的方法:

public static List<KeyValuePair<int, string>> GetStatuses()
    {
        using (var con = new SqlConnection())
        {
            var sql = @"SELECT ID [Key], Text [Value] from Statuses";

            return (con.Query<KeyValuePair<int, string>>(sql.ToString(), commandType: commandType:Text) ?? Enumerable.Empty<KeyValuePair<int, string>>()).ToList();
        }
    }

3 个答案:

答案 0 :(得分:5)

当您编写new { s.Key, s.Value }时,您正在实例化一个包含属性KeyValue的新匿名类型。相反,您可能希望通过编写KeyValuePair来使用new KeyValuePair(s.Key, s.Value)的构造函数。

另请注意,您的Where子句已经过滤了KeyValuePairs的列表,因此甚至不需要投影。换句话说,在这种情况下,您可以删除整个Select语句。

因此,您可以使用KeyValuePair构造函数并编写:

tp = st.Where(s => s.Key == (int)Status.Open || s.Key == (int)Status.Reviewed)
       .Select(kvp => new KeyValuePair(kvp.Key, kvp.Value)).ToList();

或者,更好的是,只需删除Select语句:

tp = st.Where(s => s.Key == (int)Status.Open || s.Key == (int)Status.Reviewed).ToList();

关于匿名类型的更多信息:匿名类型是一种C#功能,允许您使用自定义属性制作快速的临时类。它们对Linq个查询特别有用。当您的程序编译时,会发出一个新的匿名类型,其中包含2个名为KeyValue的属性。你可以在没有名字的情况下创建一个具有2个属性的新类(完全成熟的类和匿名类之间存在一些其他差异,但这是一种考虑它的便捷方式)。您的方法应返回KeyValuePairs列表,但您已提供此新类型的对象列表。详细了解他们here

作为一般性小调,您根本不需要声明tp变量。相反,您可以在return声明中switch

答案 1 :(得分:4)

正如其他人已经指出的那样,您在Select创建了一个新的匿名类型,而不是KeyValuePair。但是,您已经在使用KeyValuePair,因此您甚至不需要Select

tp = st.Where(...where...).ToList();

实际上没有必要重新实例化Select中的对象(除非你想要一个新的引用......但在这种情况下KVP是不可变的)。 Where.ToList更具表现力,仅仅是因为它不那么容易,至少恕我直言

答案 2 :(得分:2)

您无法将匿名对象{ Key, Value }列表分配给类型为KeyValuePair<int,string>的变量。如果您要重复使用KeyValuePair调用返回的相同GetStatuses()实例,则只需删除Select投影即可。否则,将每个键值对投影到KeyValuePair<int,string>类型的新实例(下面的取消注释行):

switch(status)
{
    case (int)Status.Completed:
         tp = st.Where(s => s.Key == (int)Status.Completed || s.Key == (int)Status.NotValid)  
                //.Select(s => new KeyValuePair<int, string>(s.Key, s.Value))
                .ToList();
         break; // also make sure you have break here
     case (int)Status.Open:
          tp = st.Where(s => s.Key == (int)Status.Open || s.Key == (int)Status.Reviewed)
                 //.Select(s => new KeyValuePair<int, string>(s.Key, s.Value))
                 .ToList();
         break;
}