优雅地将列表和对象作为参数传递

ean*_*533 13 c#

在C#中,可以使用params关键字为方法指定任意数量的类型化参数:

public void DoStuff(params Foo[] foos) {...}

public void OtherStuff {
    DoStuff(foo1);
    DoStuff(foo2, foo3);
}
Run Code Online (Sandbox Code Playgroud)

如果您已有对象列表,则可以将其转换为数组以传递给此方法:

DoStuff(fooList.ToArray());
Run Code Online (Sandbox Code Playgroud)

但是,有没有任何优雅的混合方式?也就是说,传入多个对象和对象列表,并将结果展平为一个列表或数组?理想情况下,我希望能够像这样调用我的方法:

DoStuff(fooList, foo1, foo2, anotherFooList, ...);
Run Code Online (Sandbox Code Playgroud)

截至目前,我知道如何做到这一点的唯一方法是将所有内容预处理到一个列表中,我不知道有什么方法可以做到这一点.

编辑:要清楚,我没有与params关键字结合,它只是一个相关的机制,帮助我解释我想做的事情.我很满意任何看起来干净的解决方案,并将所有内容整合到一个列表中.

Lee*_*Lee 12

您可以创建一个带有隐含转换的类来包装单个元素和列表:

public class ParamsWrapper<T> : IEnumerable<T>
{
    private readonly IEnumerable<T> seq;

    public ParamsWrapper(IEnumerable<T> seq)
    {
        this.seq = seq;
    }

    public static implicit operator ParamsWrapper<T>(T instance)
    {
        return new ParamsWrapper<T>(new[] { instance });
    }

    public static implicit operator ParamsWrapper<T>(List<T> seq)
    {
        return new ParamsWrapper<T>(seq);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return this.seq.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以改变你的DoStuff方法:

private static void DoStuff(params ParamsWrapper<Foo>[] foos)
{
    Foo[] all = foos.SelectMany(f => f).ToArray();
    //
}
Run Code Online (Sandbox Code Playgroud)

  • +1.这很聪明,作为OP提出的难题的答案:)虽然我很确定它也是"邪恶的":)(在Jon Skeet的意义上,例如在这个谈话中:http://youtu.be/ lGbQiguuUGc).我不认为它应该进入生产代码,但它很好 (2认同)
  • 啊,这是我一直在寻找的那种答案.不是因为我想在制作中使用它,而是因为我知道这个问题的聪明答案会教会我一些新东西.非常好,谢谢. (2认同)