【问题标题】:How do you set a type to an IEnumerable<> if the results will have many types?如果结果有多种类型,如何将类型设置为 IEnumerable<>?
【发布时间】:2012-10-10 14:03:20
【问题描述】:

问题我正在用我之前制作的程序在这里尝试一些新的东西。在第一个程序中,我能够拖放表适配器并使用通用“var”来存储查询结果。现在我正在尝试创建一个具有一些代码分离的新程序。例如,在第一个程序中,我将所有代码都写在 form.cs 文件中,这次我想创建一个类来运行查询并将它们返回给调用类,但是,如何存储查询结果包含多种类型?您不能返回 var 变量,它必须更具体。我在选择行上收到错误消息:“无法将类型'System.Collections.Generic.IEnumerable' 隐式转换为'System.Collections.Generic.IEnumerable;。存在显式转换(您是否缺少演员表?)

有人可以帮助我吗?演员阵容是什么?第一种方法 (public IEnumerable getList()) 按预期工作,它的第二种方法 (public IEnumerable getRecipeInfo(string recipeName)) 出现错误。到目前为止,这是我的代码。

namespace recipeDataBase
{
    class Query
    {
        recipiesNewDataSet recipeDataSet = new recipiesNewDataSet();
        recipiesNewDataSetTableAdapters.RecipeTableAdapter recipeTableAdapter = new recipiesNewDataSetTableAdapters.RecipeTableAdapter();
        recipiesNewDataSetTableAdapters.RecipeIngredientTableAdapter ingredientTableAdapter = new recipiesNewDataSetTableAdapters.RecipeIngredientTableAdapter();
        recipiesNewDataSetTableAdapters.RatingTableAdapter ratingTableAdapter = new recipiesNewDataSetTableAdapters.RatingTableAdapter();

        public  Query()
        {

        }

        public IEnumerable<string> getList()
        {
            recipeTableAdapter.Fill(recipeDataSet.Recipe);

            IEnumerable<string> recipeList = (from a in recipeDataSet.Recipe
                                              select a.RecipeName);
            return recipeList;
        }

        public IEnumerable<string> getRecipeInfo(string recipeName)
        {
            recipeTableAdapter.Fill(recipeDataSet.Recipe);
            ratingTableAdapter.Fill(recipeDataSet.Rating);
            ingredientTableAdapter.Fill(recipeDataSet.RecipeIngredient);
            IEnumerable<string> recipeInfo = (from a in recipeDataSet.Recipe
                                              from b in recipeDataSet.Rating
                                              from c in recipeDataSet.RecipeIngredient
                                              where a.RecipeName == recipeName &&
                                              a.RecipeNum == c.RecipeNum &&
                                              a.RatingNum == b.RatingNum
                                              select new { a.RecipeName, a.Nationality, a.Event, a.Source, b.FamilyRating, c.Ingredient });
            return recipeInfo;
        }

    }
}

提前感谢您的帮助!

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    您遇到了异常,因为您在查询中选择了匿名类型,但查询变量的类型是 IEnumerable&lt;string&gt;。相反,您必须选择一个字符串,使用 var 关键字或自定义类。

    如果你想返回一些有用的东西,我会创建一个自定义类,其中包含你在匿名类型中选择的所有这些属性,例如:

    public class Recipe
    {
        public String RecipeName{ get; set;}
        public String Nationality{ get; set;}
        public String Event{ get; set;}
        // ...
    }
    

    然后您可以从方法中返回一个IEnumerable&lt;Recipe&gt;,并在查询中选择实例:

    ...
    select new Recipe(){ RecipeName=a.RecipeName, Nationality=a.Nationality, Event=a.Event,... });
    

    旁注:我建议在查询中使用Join 而不是Where

    Why is LINQ JOIN so much faster than linking with WHERE?

    【讨论】:

    • 好的,所以我创建了一个带有公共属性的新类 Recipe 以及 get 和 set 方法,现在我的 Query 类说 recipeDataBase.Recipe'不包含'add'的定义
    • @CraigSmith:add 是什么?您不需要将其添加到某些内容中。只需选择它,如上所示。简化示例(无连接):IEnumerable&lt;Recipe&gt; recipeInfo=from a in recipeDataSet.Recipe select new Recipe(){RecipeName=a.RecipeName, Nationality=a.Nationality, Event=a.Event};
    • 嗯,修复了添加问题,现在我又回到了不能隐式......你错过了演员表吗?
    • @CraigSmith:是的,您需要返回IEnumerable&lt;Recipe&gt; 而不是IEnumerable&lt;String&gt;,所以更改方法签名。
    • 问题仍然出在 select 语句上
    【解决方案2】:

    您使用的是匿名类型,因此:

            var recipeInfo = (from a in recipeDataSet.Recipe
                                              from b in recipeDataSet.Rating
                                              from c in recipeDataSet.RecipeIngredient
                                              where a.RecipeName == recipeName &&
                                              a.RecipeNum == c.RecipeNum &&
                                              a.RatingNum == b.RatingNum
                                              select new { a.RecipeName, a.Nationality, a.Event, a.Source, b.FamilyRating, c.Ingredient }).ToList();
    

    ...给你一个匿名类型的 IEnumerable,它有 6 个值,可能都是字符串。 var 不代表“variant”,is 仍然是一个强类型声明,只是在编译时解析(如果无法从使用中推断出类型,则会失败) .因此,上面的代码在编译时使var 表示IEnumerable&lt;anonymous_type_with_6_strings&gt;,但return 语句试图使这个IEnumerable&lt;string&gt; - 这是你得到编译时的地方强制转换异常。

    我建议您创建一个简单的类来保存 RecipeInfo 值,这样您的方法就可以返回 IEnumerable&lt;RecipeInfo&gt;

    class RecipeInfo
    {
        public string RecipeName {get;set;}
        public string Nationality {get;set;}
        public string Event {get;set;}
        public string Source {get;set;}
        public string FamilyRating {get;set;}
        public string Ingredient {get;set;}
    }
    

    然后您可以将您的选择投影到这种类型中:

        var recipeInfo = (from a in recipeDataSet.Recipe
                                          from b in recipeDataSet.Rating
                                          from c in recipeDataSet.RecipeIngredient
                                          where a.RecipeName == recipeName &&
                                          a.RecipeNum == c.RecipeNum &&
                                          a.RatingNum == b.RatingNum
                                          select new RecipeInfo{RecipeName=a.RecipeName, Nationality=a.Nationality, Event=a.Event, Source=a.Source, FamilyRating=b.FamilyRating, Ingredient=c.Ingredient }).ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-19
      • 2011-04-13
      相关资源
      最近更新 更多