Roslyn - 从yield'ed IEnumerable <t>创建SeparatedList <t> </t> </t>

时间:2013-07-24 18:18:58

标签: c# ienumerable roslyn

我正在尝试使用动态生成的SeparatedList序列(由IEnumerable函数调用构建)来构建Enumerable.Select()。用于创建SeparatedList的API函数有两个参数:IEnumerable<T>IEnumerable<SyntaxToken>。我提供了一个简单的函数Repeat,它是一个无限序列生成器,在这种情况下产生尽可能多的逗号。

SeparatedList函数似乎消耗了第一个序列(此处为参数类型)的数量,因为第二个序列中有条目,这会让我感到困惑。我是否误解了该功能应该如何工作,还有其他人这样做过吗?感谢

Syntax.SeparatedList<ParameterSyntax>(
    functionParameterTypes,Repeat(i=>Syntax.Token(SyntaxKind.CommaToken)))

(编辑:我应该补充一点,将functionParameterTypes转换为List<>并传递另一个List<>,而functionParameterTypes中的元素少于{{1}},但我正在尝试要做到这一点,而不必提前明确地建立列表。)

2 个答案:

答案 0 :(得分:0)

separators参数的XML文档说:

  

令牌数必须比节点数少一个。

这是正确的,这不是方法实际需要的:令牌数量必须比节点数量少一个或者与令牌数量相同。如果这是故意的话,我不会感到惊讶,如果您正在尝试处理刚刚编写的代码,f(foo, bar, )之类的代码是有意义的。

我认为在参数序列上调用ToList()是最好的选择。而且您不必使用其他List作为分隔符,您可以使用Enumerable.Repeat()。例如像这样(taken from a library I wrote where I faced the same issue):

public static SeparatedSyntaxList<T> ToSeparatedList<T>(
    this IEnumerable<T> nodes, SyntaxKind separator = SyntaxKind.CommaToken)
    where T : SyntaxNode
{
    var nodesList = nodes == null ? new List<T>() : nodes.ToList();
    return Syntax.SeparatedList(
        nodesList,
        Enumerable.Repeat(
            Syntax.Token(separator), Math.Max(nodesList .Count - 1, 0)));
}

答案 1 :(得分:0)

我也有同样需要使用动态生成的参数列表创建SeparatedList。我的解决方案是使用SelectMany()Take()向参数添加分隔符(即“逗号”),但随后删除最后一个尾随逗号。

        SyntaxFactory.SeparatedList<ParameterSyntax>(
            functionParameterTypes
                .SelectMany(param =>
                    new SyntaxNodeOrToken[]
                    {
                        param,
                        SyntaxFactory.Token(SyntaxKind.CommaToken)
                    })
                .Take(functionParameterTypes.Count() * 2 - 1)
        );