Передача массива в функцию, которая принимает объект 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);
Выглядит менее раздутым и более читаемым для меня.