从IEnumerable到List的无效转换

Dar*_*olt 1 c# casting type-conversion

我正在Unity3D项目中处理一个C#脚本,我正在尝试获取字符串列表并获得排列的2D列表.以下列方式使用此答案 GetPermutations():

List<string> ingredientList = new List<string>(new string[] { "ingredient1", "ingredient2", "ingredient3" });

List<List<string>> permutationLists = GetPermutations(ingredientList, ingredientList.Count);
Run Code Online (Sandbox Code Playgroud)

但它会引发隐式转换错误:

IEnumerable<IEnumerable<string>> to List<List<string>> ... An explicit conversion exists (are you missing a cast)?

所以我看了几个地方,比如这里,并提出了以下修改:

List<List<string>> permutationLists = GetPermutations(ingredientList, ingredientList.Count).Cast<List<string>>().ToList();
Run Code Online (Sandbox Code Playgroud)

但它在运行时中断,在内部处理,并允许它继续而不指示失败 - 可能是因为它在Unity3D中运行.这是我在停止调试脚本后在Unity3D中看到的内容:

InvalidCastException: Cannot cast from source type to destination type.
System.Linq.Enumerable+<CreateCastIterator>c__Iterator0`1[System.Collections.Generic.List`1[System.String]].MoveNext ()
System.Collections.Generic.List`1[System.Collections.Generic.List`1[System.String]].AddEnumerable (IEnumerable`1 enumerable) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/List.cs:128)
System.Collections.Generic.List`1[System.Collections.Generic.List`1[System.String]]..ctor (IEnumerable`1 collection) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/List.cs:65)
System.Linq.Enumerable.ToList[List`1] (IEnumerable`1 source)
Run Code Online (Sandbox Code Playgroud)

我认为这仍然是错误的,所以我也尝试了以下方法和更多我不记得的方法:

List<List<string>> permutationLists = GetPermutations(ingredientList, ingredientList.Count).Cast<List<List<string>>>();

List<List<string>> permutationLists = GetPermutations(ingredientList.AsEnumerable(), ingredientList.Count);
Run Code Online (Sandbox Code Playgroud)

以及在方法调用之前使用括号显式转换,就像在C或Java中一样,仍然无济于事.


那么我应该如何从GetPermutations()函数中转换结果来得到一个List<List<string>>?或者,我怎么能修改函数只返回,List<List<string>>因为我不需要它为泛型类型工作?我尝试自己修改方法如下:

List<List<string>> GetPermutations(List<string> items, int count)
{
    int i = 0;
    foreach(var item in items)
    {
        if(count == 1)
            yield return new string[] { item };
        else
        {
            foreach(var result in GetPermutations(items.Skip(i + 1), count - 1))
                yield return new string[] { item }.Concat(result);
        }

        ++i;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,<T>从函数名中删除它后,它断言主体不能是迭代器块.我没有C#的经验,而且我在强类型语言中使用模板函数生锈,所以任何解释/帮助都是值得赞赏的.

我不确定如何看待这个问题,所以如果这是一个重复只是发布在这里,我会立即删除这个帖子.

Eri*_*ert 8

那么我应该如何从GetPermutations()函数中转换结果来获取a List<List<string>>

最佳解决方案:不要.为什么需要首先将序列转换为列表?将其保留为序列序列.

如果你必须:

GetPermutations(...).Select(s => s.ToList()).ToList()
Run Code Online (Sandbox Code Playgroud)

如果要修改原始方法,只需执行相同的操作:

IEnumerable<List<string>> GetPermutations(List<string> items, int count)
{
    int i = 0;
    foreach(var item in items)
    {
        if(count == 1)
            yield return new List<T>() { item };
        else
        {
            foreach(var result in GetPermutations(items.Skip(i + 1), count - 1))
                yield return (new string[] {item}.Concat(result)).ToList();
        }

        ++i;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后做GetPermutations(whatever).ToList(),你有一个列表清单.但同样,不要这样做.如果可能,请将所有内容保持在序列中.

我想将序列转换为一个列表,以便我可以按字母顺序对元素进行排序,并将它们重新连接为一个排序的,单个逗号分隔的字符串.

好的,然后那样做.让我们将您的方法重写为扩展方法Permute().让我们制作一些新的单线方法:

static public string CommaSeparate(this IEnumerable<string> items) =>
  string.Join(",", items);

static public string WithNewLines(this IEnumerable<string> items) =>
  string.Join("\n", items);

static public IEnumerable<string> StringSort(this IEnumerable<string> items) =>
  items.OrderBy(s => s);
Run Code Online (Sandbox Code Playgroud)

然后我们有以下内容 - 我将对这些类型进行注释:

string result = 
  ingredients                    // List<string>
  .Permute()                     // IEnumerable<IEnumerable<string>>
  .Select(p => p.StringSort())   // IEnumerable<IEnumerable<string>>
  .Select(p => p.CommaSeparate())// IEnumerable<string>
  .WithNewLines();                   // string
Run Code Online (Sandbox Code Playgroud)

我们已经完成了. 看看代码在做出一件事并做得好的方法时是多么清晰明了.看看按顺序保存所有内容是多么容易.