Там какой-либо путь состоит в том, чтобы сделать что-то вроде этого в C#?

Там какой-либо путь состоит в том, чтобы сделать что-то вроде этого в C#?

public void DoSomething(string parameterA, int parameterB)
{

}

var parameters = ("someValue", 5);
DoSomething(parameters);
10
задан Alon Gubkin 30 April 2010 в 22:19
поделиться

14 ответов

Закрыть, но, к сожалению, только с использованием объекта (так что вы получите много упаковки / распаковки)

public void DoSomething(params object[] parameters)
{

}

var parameters = new object[]{"someValue", 5};
DoSomething(parameters); // this way works
DoSomething("someValue", 5); // so does this way
21
ответ дан 3 December 2019 в 13:12
поделиться

Если все они одного типа, да, вы можете сделать что-нибудь с этим эффектом:

public void Print(params string[] args) {
  foreach (string arg in args) {
    Console.WriteLine(arg);
  }
}

// ...

Print("apple", "banana");
Print("apple", "banana", "cherry");
Print("apple", "banana", "cherry", "doughnut");

В противном случае, вы не можете развернуть параметры в таком месте без использования отражения. В C # нет эквивалента оператора splat в Ruby .

1
ответ дан 3 December 2019 в 13:12
поделиться

Не сегодня, нет. В настоящее время мы создаем прототип именно этой функции для возможной гипотетической будущей версии C #.

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

(Помните, что предположения Эрика о возможных гипотетических будущих выпусках C # предназначены только для развлекательных целей и не должны толковаться как обещания, что такой выпуск когда-либо будет любой конкретный набор функций.)

14
ответ дан 3 December 2019 в 13:12
поделиться

Вы можете сделать это (.NET 4.0):

var parameters = Tuple.Create("someValue", 5);

DoSomething(parameters.Item1, parameter.Item2);
2
ответ дан 3 December 2019 в 13:12
поделиться

Как насчет этого в .NET 4 (ради любопытства)

 public void DoSomething(string parameterA, int parameterB)
 {
 } 

 public void Helper(dynamic parameter)
 {
     DoSomething(parameter.Parameter1, parameter.Parameter2);
 }

 var parameters = new {Parameter1="lifeUniverseEverything", Parameter2=42};

 Helper(parameters);
0
ответ дан 3 December 2019 в 13:12
поделиться

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

using System;
using System.Reflection;

namespace SO2744885
{
    class Program
    {
        public void DoSomething(string parameterA, int parameterB)
        {
            Console.Out.WriteLine(parameterA + ": " + parameterB);
        }

        static void Main(string[] args)
        {
            var parameters = new object[] { "someValue", 5 };
            Program p = new Program();
            MethodInfo mi = typeof(Program).GetMethod("DoSomething");
            mi.Invoke(p, parameters);
        }
    }
}

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

8
ответ дан 3 December 2019 в 13:12
поделиться

нет - это невозможно.

4
ответ дан 3 December 2019 в 13:12
поделиться

Может быть этот способ более "чистый":

// standard method calling
DoSomething( "Johny", 5 );
// since C# 4.0 you can used "named parameters"
DoSomething( name: "Johny", number: 5 );
// calling with parameter's "container"
DoSomething( new DoSomethingParameters( "Johny",  5 ) );
// calling with parameter's "container"
DoSomething( new DoSomethingParameters{ Name = "Johny", Number = 5 } );
// calling with callback for parameters initialization
DoSomething( p => { p.Name = "Johny"; p.Number = 5; } );

// overload of DoSomething method with callback, which initialize parameters
public void DoSomething( Action<DoSomethingParameters> init ) {
    var p = new DoSomethingParameters();
    init( p );
    DoSomething( p );
}

// overload of DoSomething method for calling with simple parameters
public void DoSomething( string name, int number ) {
    var p = new DoSomethingParameters( name, number );
    DoSomething( p );
}
// the "main executive" method which is "doing the work"
// all posible parameters are specified as members of DoSomethingParameters object
public void DoSomething( DoSomethingParameters p ) { /* ... */ }

// specify all parameters for DoSomething method
public class DoSomethingParameters {
    public string Name;
    public int Number;

    public DoSomethingParameters() { }
    public DoSomethingParameters( string name, int number ) {
        this.Name = name;
        this.Number = number;
    }
}
3
ответ дан 3 December 2019 в 13:12
поделиться

Вдохновленный ответом Стивена:

static public void Execute<T1, T2>(this Tuple<T1, T2> parameters, Action<T1, T2> action)
{
    action(parameters.Item1, parameters.Item2);
}

var parameters = Tuple.Create("someValue", 5);
parameters.Execute(DoSomething);
3
ответ дан 3 December 2019 в 13:12
поделиться

Мне нравится ответ Хенрика, за исключением того, что он навязывает несколько странный синтаксис: параметры вызывают метод сами на себя. Я бы сделал это наоборот. Единственная проблема с этим подходом в том, что он заставляет вас явно приводить метод к делегату.

В любом случае, вот основная идея:

// wrapped code to prevent horizontal overflow
public static void Execute<T1, T2>
(this Action<T1, T2> action, Tuple<T1, T2> parameters) {
    action(parameters.Item1, parameters.Item2);
}

И так далее (для более Ts).

Использование:

var parameters = Tuple.Create("Hi", 10);

Action<string, int> action = DoSomething;

action.Execute(parameters);

Вы также можете легко сделать это с возвращаемым значением:

// wrapped code to prevent horizontal overflow
public static TResult Return<T1, T2, TResult>
(this Func<T1, T2, TResult> func, Tuple<T1, T2> parameters) {
    return func(parameters.Item1, parameters.Item2);
}

И так далее.

Я также хотел бы отметить, что если вы не находитесь на .NET 4.0, это не значит, что вы не можете легко реализовать свой собственный тип Tuple.

3
ответ дан 3 December 2019 в 13:12
поделиться

вы можете:

public void DoSomething(string parameterA, int parameterB)
{

}

var func = (Action)(() => DoSomething("someValue", 5));
func();
2
ответ дан 3 December 2019 в 13:12
поделиться

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

public void DoSomething(string parameterA, int parameterB)
{
  // Original do Something
}

public void DoSomething(object[] parameters)
{
   // some contract check whether the parameters array has actually a good signature
   DoSomething(parameters[0] as string,(parameters[1] as int?).Value);
}

var parameters = new object[]{"someValue", 5};
DoSomething(parameters);

Вы также можете попробовать некоторые возможности LinFu.Reflection, такие как Late Binding. С его помощью вы можете сделать что-то вроде этого:

var dosomethingobject = new ObjectThatHasTheDoSomething();
DynamicObject dynamic = new DynamicObject(dosomethingobject);

var parameters = new object[]{"someValue", 5};
dynamic.Methods["DoSomething"](parameters);

Для этого вам нужно, чтобы метод DoSomething находился внутри объекта.

1
ответ дан 3 December 2019 в 13:12
поделиться

«var» просто представляет определенный тип, это фактически сокращение для записи имени типа. Выше вы не указываете какой-либо тип. Единственный способ сделать это - создать класс параметров для массового представления входных данных ...

public void DoSomething(Parameters param)
{
...
}

var param = new Parameters("someValue", 5);
DoSomething(param);

... но это будет полезно только в определенных обстоятельствах. Вы можете создать несколько конструкторов Parameters для представления различных порядков параметров, но вызываемая функция будет принимать только ОДИН ввод - объект Parameters. Таким образом, вы действительно подрываете возможность перегрузки функции.

Короче говоря, нет. =)

0
ответ дан 3 December 2019 в 13:12
поделиться

Нет необходимости использовать отражение, если вы сначала храните как делегат, но это требует сильного объявления делегата.

public void DoSomething(string parameterA, int parameterB)
{
    Console.WriteLine(parameterA+" : "+parameterB);
}
void Main()
{

    var parameters = new object[]{"someValue", 5};
    Action<string,int> func=DoSomething;
    func.DynamicInvoke(parameters);

}

...и вы можете забыть о проверке типа/самостоятельности списка параметров во время компиляции. Вероятно, это плохо.

10
ответ дан 3 December 2019 в 13:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: