Передача массива аргумента в функцию с несколькими параметрами в C # - PullRequest
4 голосов
/ 11 февраля 2012

Жизнь коротка

def foo(b,a,r):
    # bla bla bla
    pass

mylist = ['b','a','r']
foo(*mylist) 

Вот так передает список аргументов в метод несколько позиционных параметров в Python .

Но в C # я обнаружил, передает массив в параметр массива , используя params ключевые слова, подобные этому:

void foo(params string[] bar)
{
    // bla bla bla
}

string[] mylist = {"b", "a", "r"};
foo(mylist)

Представьте себе, как Если я не могу коснуться функции, есть ли более простой способ? Есть ли способ сделать это?

Вот что я имею в виду:

void foo (string b, string a, string r)
{
    // bla bla bla
}

string[] mylist = {"b", "a", "r"};
foo(mylist[0],mylist[1],mylist[2]); // This line makes my life difficult

Я ищу в Интернете и не могу найти альтернативу.Просто хочу убедиться, что я не пропустил скрытую функцию, которую предоставляет C #.Кто знает, что для нас такой ярлык?

Ответы [ 5 ]

3 голосов
/ 11 февраля 2012

Нет, в C # нет функции, позволяющей вам сделать это напрямую.Но есть несколько способов обойти это:

  1. Создать метод, который преобразует метод с несколькими параметрами в метод с одним параметром массива:

    static Action<T[]> ToArrayMethod<T>(Action<T, T, T> original)
    {
        return array => original(array[0], array[1], array[2]);
    }
    

    А затем используйте его следующим образом:

    string[] array = {"b", "a", "r"};
    
    var arrayFoo = ToArrayMethod(foo);
    
    arrayFoo(array);
    

    Недостатком этого подхода является то, что этот метод работает только для методов с ровно тремя параметрами с типом возврата void.Вам нужно будет написать еще одну перегрузку ToArrayMethod(), если вы хотите, чтобы это работало для методов с, скажем, 4 параметрами или для тех, которые возвращают какое-либо значение.При этом аргументы передаются с использованием массива:

    var foo = typeof(SomeType)
        .GetMethod("foo", BindingFlags.Instance | BindingFlags.NonPublic);
    
    object[] array = {"b", "a", "r"};
    
    foo.Invoke(somTypeInstance, array);
    
1 голос
/ 11 февраля 2012

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

Вот пример подхода:

string[] mylist = { "b", "a", "r" };
((Action<string,string,string>)foo).DynamicInvoke(mylist);
1 голос
/ 11 февраля 2012

Есть недостатки в использовании статических языков, и это один из них, если ваша сигнатура функции определена как:

void foo (string a, string b, string c);

, то вы вынуждены передать 3 отдельные строки

foo(mylist[0],mylist[1],mylist[2]);

единственный способ иметь гибкие входы в C # - это использовать params , который вы уже используете, или использовать значения по умолчанию (C # 4.0):

void foo (string a, string b = null, string c = null)

, что означает, что еслиЯ не передаю b или c, просто устанавливаю их в null, и теперь вы можете вызывать свою функцию следующим образом:

foo(mylist[0]) 
0 голосов
/ 11 февраля 2012

Итак, чтобы суммировать множество ответов здесь, вам понадобится что-то вроде хака для этого, и, на мой взгляд, самый чистый способ - что-то вроде этого:

Создание функции расширения для перечислимых элементов:

public static class Extensions
{
    public static void SendToMethod<T>(this IEnumerable<T> self, Delegate func  )
    {
        Contract.Requires(func.Method.GetParameters().Length == self.Count());
        func.DynamicInvoke(self.Cast<object>().ToArray());
    }
}

Затем вы можете отправить массив любой функции с числом аргументов, равным длине перечислимого:

public void foo(string a, int b, bool c, string d) {}
public void foo2(string a, string b, string c) {}

...
var test1 = new object[] {"ASDF", 10, false, "QWER"};
var test2 = new[] {"A", "B", "C"};

test2.SendToMethod((Action<string, string, string>)foo);
test1.SendToMethod((Action<string, int, bool, string>)foo2); 
0 голосов
/ 11 февраля 2012

Нет ярлыка. Если вы хотите сойти с ума и можете несколько изменить функцию, вы можете перегрузить ее, чтобы иметь одну сигнатуру с ключевым словом params, и исходная перегрузка передает свои аргументы в новую.

...