Передача массива в функцию, которая принимает объект params [] или IEnumerable <T>

Я хочу передать массив настраиваемых объектов к функции типа String.Join, которая имеет следующие подписи:

  • public static string Join(string separator, params Object[] values)
  • public static string Join(string separator, IEnumerable<T> 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<T>:

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

Но можно ли вызвать функцию params object[]? В критическом сценарии производительности было бы предпочтительнее обращаться к массиву напрямую, а не через счетчик.

Я использую С# 4.0, если это имеет значение.

Ответ 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);

To:

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

Чтобы узнать больше об этой теме, выполните исследования С# с перегрузкой.

Разрешение перегрузки - это интересный предмет, но я все же считаю его узким местом для проблемы с производительностью.

Ответ 5

Если вы используете IEnumerable, вы можете использовать общую перегрузку <object> метода ToArray():

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

Выглядит менее раздутым и более читаемым для меня.