Как вызвать метод с инициализатором коллекции C #?

Дело

Этим утром я реорганизовал некоторый метод ведения журнала, и мне нужно было изменить параметр метода 'params' в обычном массиве. Следовательно, вызов метода должен был измениться параметром массива. Я бы хотел, чтобы вызов метода менялся как можно реже, поскольку это широко используемый служебный метод.

Я предполагал, что смогу использовать инициализатор коллекции для вызова метода, но это дало мне ошибку компиляции. См. Второй вызов в примере ниже. Третий вызов тоже подойдет, но тоже приведет к ошибке.

Пример

void Main()
{
    // This works.
    object[] t1 = { 1, "A", 2d };
    Test(t1);

    // This does not work. Syntax error: Invalid expression term '{'.
    Test({1, "A", 2d });

    // This does not work. Syntax error: No best type found for implicitly-typed array.
    Test(new[] { 1, "A", 2d });

    // This works.
    Test(new object[] { 1, "A", 2d });
}

void Test(object[] test)
{
    Console.WriteLine(test);
}

Вопрос

  • Есть ли способ вызвать Test() без предварительной инициализации массива?

person Herman Cordes    schedule 24.03.2014    source источник
comment
Если вариант 3 работает, почему бы не использовать его?   -  person Sam Axe    schedule 24.03.2014
comment
Что ж, даже если бы вторая версия работала, она все равно инициализировала бы массив. Например, new[] { "a", "b" } в точности эквивалентен new string[] { "a", "b" } с точки зрения сгенерированного кода. Обратите внимание, что new[] не инициализатор коллекции - это просто обычный инициализатор массива с предполагаемым типом массива.   -  person Jon Skeet    schedule 24.03.2014
comment
Вот объяснение почему вариант 2 не работает: Почему компилятор не может определить тип массива объектов?   -  person Heinzi    schedule 24.03.2014
comment
@ Dan-o, я обновил чехол. Я бы хотел, чтобы вызов метода менялся как можно меньше, потому что мне пришлось бы провести много рефакторинга.   -  person Herman Cordes    schedule 24.03.2014
comment
Я чувствую себя обязанным спросить: зачем вам менять подпись, если вы хотите как можно меньше влиять на использование; что дает ваш рефакторинг? Это был метод params object[] args раньше?   -  person aevitas    schedule 24.03.2014
comment
@aevitas Да, раньше это был params object[] args. Пришлось добавить параметр [CallerMemberName]string memberName = null к сигнатуре метода для логирования. Поэтому использование params больше невозможно.   -  person Herman Cordes    schedule 24.03.2014


Ответы (1)


Проблема в том, что C # пытается определить тип массива. Однако вы предоставили значения разных типов, и поэтому C # не может сделать вывод о типе. Либо гарантирует, что все ваши значения относятся к одному типу, либо явно указывайте тип при инициализации массива.

var first = new []{"string", "string2", "string3"};
var second = new object[]{0.0, 0, "string"};

Как только вы перестанете использовать параметры, пути назад не будет. Вы будете вынуждены инициализировать массив.

Альтернативный вариант - продолжить использование параметров:

public void Test([CallerMemberName]string callerMemberName = null, params object[] test2){}
person Kasper Holdum    schedule 24.03.2014