将数组传递给接受参数 object[] 或 IEnumerable<T> 的函数

Posted

技术标签:

【中文标题】将数组传递给接受参数 object[] 或 IEnumerable<T> 的函数【英文标题】:Passing array to function that takes either params object[] or IEnumerable<T> 【发布时间】:2013-04-02 18:05:31 【问题描述】:

我想将一组自定义对象传递给像 String.Join 这样具有以下签名的函数:

public static string Join(string separator, params Object[] values) public static string Join(string separator, IEnumerable&lt;T&gt; values)

如果我这样调用函数:

var arr = new MyClass[] new MyClass(), new MyClass() ;
string text = string.Join("\n", arr);

我得到一个编译器错误:

以下方法或属性之间的调用不明确:'string.Join(string, params object[])' 和 'string.Join(string, System.Collections.Generic.IEnumerable)'

我可以使用IEnumerable&lt;T&gt; 函数解决歧义:

var arr = new MyClass[] new MyClass(), new MyClass() ;
string text = string.Join<MyClass>("\n", arr);

但是我可以调用params object[] 函数吗?

我使用的是 C# 4.0,如果这有什么不同的话。

【问题讨论】:

不使用 params object[] 重载,但在 using System.Linq; 时你可以使用 string text = string.Join("\n", myArray.AsEnumerable()); 【参考方案1】:

如果您将object[] 作为第二个参数传递,编译器应该选择object[] 重载,因为它完全匹配。如果您有一个不同类型的数组(在这种情况下为MyClass[]),只需将数组转换为object[]

string.Join("\n", (object[])arr);

您实际上并没有在运行时更改任何对象的类型或执行任何转换,您只是给编译器一个关于使用哪个重载的提示。

关于您对性能的评论,如果性能如此关键,请不要忘记对这两个选项进行基准测试。不要假设一个比另一个快。 (并且始终分析您的整个应用程序 - 任何瓶颈都可能在其他地方。)

【讨论】:

【参考方案2】:

如果您将arr 变量的类型更改为object[],您将调用另一个重载:

object[] arr = new MyClass[]  new MyClass(), new MyClass() ;
string text = string.Join("\n", arr);

您也可以将其显式转换为object[]: string.Join("\n", (object[])arr);

【讨论】:

【参考方案3】:

您可以像这样调用另一个重载(这就是 param 的用途)-

string text = string.Join("\n", new MyClass(), new MyClass());

【讨论】:

【参考方案4】:

对您的代码最简单的更改是:

    var arr = new MyClass[] new MyClass(), new MyClass() ;
    string text = string.Join("\n", arr);

收件人:

    var arr = new object[] new MyClass(), new MyClass() ;
    string text = string.Join("\n", arr);

如前所述,强制转换也有效:

    var arr = new MyClass[] new MyClass(), new MyClass() ;
    string text = string.Join("\n", (object[])arr);

要了解有关此主题的更多信息,请研究C# overload resolution。

重载解决方案本身就是一个有趣的主题,但我还没有发现它是性能问题的瓶颈。

【讨论】:

正如我在问题中提到的,我想将数组传递给我自己的函数的适当实现(不是 String.Join,而是具有类似方法签名的东西)。这里的性能差异是由于我的功能的不同实现。使用数组而不是IEnumerable&lt;T&gt; 可以更快地完成某些操作,例如获取集合中元素的数量。 Count() 扩展方法在 IEnumerable 是一个数组的情况下使用 .Length 属性,但这不是你的重点。如果性能差异如此关键,您可能需要考虑为成员使用不同的名称,而不是依赖重载解决方案。因此,您不必强制编译时类型来获得您正在寻找的语义。【参考方案5】:

如果您使用的是IEnumerable,您可以使用ToArray() 方法的&lt;object&gt; 泛型重载:

var allFoos = foo.GetAllFoos().ToArray<object>(); 
string s = string.Join(", ", allFoos); 

对我来说看起来不那么臃肿且更具可读性。

【讨论】:

以上是关于将数组传递给接受参数 object[] 或 IEnumerable<T> 的函数的主要内容,如果未能解决你的问题,请参考以下文章

如何将Object参数数组快速传递给Alamofire

Scala:无法将数组传递给需要 Seq 或 Iterable 的函数

如何将单个对象 [] 传递给参数对象 []

如何将字符串向量传递给execv

JS 数组方法

从数组或对象(而不是哈希)生成路由时,如何将“only_path:true”和“anchor:”等选项传递给“url_for”