在C#中有没有这样的方法?

在C#中有没有这样的方法?,c#,parameters,C#,Parameters,在C#中有没有这样的方法 不-这是不可能的。您可以通过反射调用它,但这会产生一些开销: using System; using System.Reflection; namespace SO2744885 { class Program { public void DoSomething(string parameterA, int parameterB) { Console.Out.WriteLine(parameter

在C#中有没有这样的方法


-这是不可能的。

您可以通过反射调用它,但这会产生一些开销:

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

当然,如果您可以将方法签名更改为采用数组,这也会起作用,但在我看来,情况会更糟。

关闭,但不幸的是,仅使用object(因此会有很多装箱/拆箱操作)


如果它们都是同一类型的,是的,您可以采取以下措施:

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#没有Ruby的等价物。你可以这样做(.NET 4.0):


如果首先存储为委托,则无需使用反射,但它确实需要对委托进行强声明

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

}
public void DoSomething(字符串参数a,int参数b)
{
Console.WriteLine(参数a+“:”+参数b);
}
void Main()
{
var参数=新对象[]{“someValue”,5};
动作func=剂量测定法;
函数DynamicInvoke(参数);
}
…而且您可以忘记参数列表的编译时类型/健全性检查。可能是一件坏事。

“var”只是表示一个特定的类型,它实际上是编写类型名的简写。在上面的示例中,您没有指定任何类型。唯一的方法是创建一个参数类来表示批量输入

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

var param = new Parameters("someValue", 5);
DoSomething(param);
…但这只在特定情况下有用。您可以创建多个参数构造函数来表示参数的不同排列,但是您正在调用的函数将只接受一个输入-Parameters对象。因此,这样做实际上破坏了函数重载的能力

因此,简而言之,你可以做:

public void DoSomething(string parameterA, int parameterB)
{

}

var func = (Action)(() => DoSomething("someValue", 5));
func();
也许这样更“干净”:

//标准方法调用
DoSomething(“Johny”,5);
//由于C#4.0,您可以使用“命名参数”
DoSomething(名称:“Johny”,编号:5);
//使用参数的“容器”调用
DoSomething(新DoSomething参数(“Johny”,5));
//使用参数的“容器”调用
DoSomething(新的DoSomething参数{Name=“Johny”,编号=5});
//使用回调函数调用参数初始化
DoSomething(p=>{p.Name=“Johny”;p.Number=5;});
//带有回调的DoSomething方法重载,该方法初始化参数
公共无效剂量测定(初始行动){
var p=新的DoSomethingParameters();
init(p);
剂量测定法(p);
}
//使用简单参数调用DoSomething方法的重载
公共void DoSomething(字符串名称、整数){
var p=新的DoSomethingParameters(名称、编号);
剂量测定法(p);
}
//“主要执行”方法,即“做工作”
//所有可能的参数都指定为DoSomethingParameters对象的成员
公共无效DoSomething(DoSomethingParameters p){/*…*/}
//指定剂量测定法的所有参数
公共类DoSomethingParameters{
公共字符串名称;
公共整数;
公共DoSomethingParameters(){}
公共DoSomethingParameters(字符串名称、整数){
this.Name=Name;
这个。数字=数字;
}
}
在.NET4中如何(出于好奇)


受史蒂文回答的启发:

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);
static public void Execute(此元组参数,动作)
{
动作(parameters.Item1,parameters.Item2);
}
var参数=Tuple.Create(“someValue”,5);
参数。执行(DoSomething);

如果不想更改方法签名,为什么不声明一个具有适当签名的新方法,并将其用作代理。像

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);
你也可以尝试一些东西,比如后期绑定。使用它,您可以执行以下操作:

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

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

为此,您需要将
DoSomething
方法放在对象内部。

不是现在,不是。我们目前正在为可能的假设未来版本的C#制作该功能的原型

如果你能提供一个非常棒的理由来解释为什么你想要这个特性,那么这将是将它从原型设计中实际应用到一个可能的未来版本中的要点。你的精彩场景是什么激发了这一功能


(请记住,Eric关于C#未来可能的假设版本的推测仅用于娱乐目的,不能被解释为承诺会有这样的版本或有任何特定的功能集。)

我喜欢Henrik的回答,除了它强加了一种有点奇怪的语法:参数本身调用一个方法。我会反过来做。这种方法唯一的问题是,它使您显式地将方法强制转换为委托

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

}
无论如何,这里有一个基本的想法:

// 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);
}
您还可以使用返回值轻松完成此操作:

// 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);
}
//防止水平溢出的包装代码
公共静态TResult返回
(此函数,元组参数){
返回func(parameters.Item1,parameters.Item2);
}
等等


我还想指出,仅仅因为您不在.NET 4.0上,这并不意味着您不能轻松实现自己的
元组类型。

只是好奇,这有什么意义吗?我真的不能添加比其他答案添加的更多的内容,但我只是好奇您为什么要这样做。我不是说有什么负面的意思,只是当我看到人们做了一些不寻常的事情(像这样),我不禁想知道为什么他们会采取这种方式。嗯,我只是一个好奇的人。:)当然,出于教育目的,这是有道理的,但我想不出有什么理由可以解决我从未遇到过的一些模糊问题。我认为这个答案没有抓住要点。这将更接近于询问
DoSomething
函数是否接受元组并跨原始参数“解包”元组。(但C#没有这样的功能。)我同意
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);
var dosomethingobject = new ObjectThatHasTheDoSomething();
DynamicObject dynamic = new DynamicObject(dosomethingobject);

var parameters = new object[]{"someValue", 5};
dynamic.Methods["DoSomething"](parameters);
// 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);
}
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);
}