Roslyn-创建一个SeparatedList<;T>;从产量';ed IEnumerable<;T

本文关键字:lt IEnumerable ed gt 创建 一个 SeparatedList Roslyn- | 更新日期: 2023-09-27 18:24:41

我正在尝试使用动态生成的IEnumerable序列(由Enumerable.Select()函数调用构建)来构建SeparatedList。创建SeparatedList的API函数采用两个参数:IEnumerable<T>IEnumerable<SyntaxToken>。我提供了一个简单的函数Repeat,它是一个无限序列生成器,在本例中,根据需要生成任意数量的逗号。

SeparatedList函数似乎消耗了与第二个序列中的条目一样多的第一个序列(此处为参数类型),这让我很困惑。我是否误解了该功能的工作方式,是否有其他人这样做?感谢

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

(编辑:我应该补充一点,将functionParameterTypes转换为List<>,并传递另一个比functionParameterTypes中的元素少一个令牌的List<>确实有效,但我正在努力做到这一点,而不必提前显式构建列表。)

Roslyn-创建一个SeparatedList<;T>;从产量';ed IEnumerable<;T

separators参数的XML文档显示:

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

你说得对,这不是该方法实际需要的:令牌的数量必须比节点的数量少一个,或者与令牌的数量相同。如果这是故意的,我不会感到惊讶,如果你试图处理刚刚编写的代码,像f(foo, bar, )这样的代码是有意义的。

我认为在参数序列上调用ToList()是最好的选择。您不必使用另一个List作为分隔符,您可以使用Enumerable.Repeat()作为分隔符。例如这样的例子(取自我写的一个图书馆,我在那里遇到了同样的问题):

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)));
}

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

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