[英]In C#, is there a way to pass an array to a method that takes in a variable length parameters?
[英]C# - pass on variable amount of parameters to other method within a method
我知道标题有点难以理解,但下面的例子应该能阐明我的意思:
想象一下,您有一个具有 2 个重载的方法:
void Method(int i)
{
Console.WriteLine("Method(int) called");
}
void Method(int i, string s)
{
Console.WriteLine("Method(int, string) called");
}
然后你有另一种方法,它采用可变数量的参数:
void MethodOverload(params dynamic[] parameters)
{
Method(parameters); // Call one of the overloading methods depending on the parameter amount and their type
}
上面的方法接受任何数量的任何类型的参数。 我想根据传递的参数数量及其类型调用其中一种重载方法。
例如:
void Run()
{
TestFuncOverload(5); // Output: "testFunc(int) called"
TestFuncOverload(5, "some text"); // Output: "testFunc(int, string) called"
TestFuncOverload(5, 5); //Error
}
如何在 C# 中实现这一目标?
我可以用下面的代码做到这一点。 它需要大量的反射,您可以考虑另一种方法来避免性能问题。
public class Test
{
private void Method(int i)
{
Console.WriteLine("Method(int) called");
}
private void Method(int i, string s)
{
Console.WriteLine("Method(int, string) called");
}
public void Method(params object[] parameters)
{
var m = typeof(Test).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
.Where(x => x.Name == "Method" &&
!x.GetParameters()
.Any(p => p.IsDefined(typeof(ParamArrayAttribute), false)))
.Where(x => x.GetParameters().Count() == parameters.Count())
.Where(x => x.GetParameters()
.Select(y => Type.GetType("System." + y.ParameterType.Name))
.Zip(parameters.Select(z => z.GetType()), Equals)
.All(q => q))
.FirstOrDefault();
if(m == null) throw new Exception ("method not found");
//null result because of void method.
var result = m.Invoke(this, parameters);
}
}
static void Main(string[] args)
{
Test t = new Test();
//"Method(int) called"
t.Method(0);
//"Method(int, string) called"
t.Method(0, "");
//throws ex
t.Method("", "");
}
你可以通过反射来做到这一点,但我不推荐它。 反射很慢,要做到这一点,您需要大量使用它。 你应该尝试用不同的方法来解决它,但如果你真的需要这样做,这应该可以解决问题:
public void MethodOverload(params dynamic[] parameters)
{
//Check if the array is null
if (parameters == null)
throw new ArgumentNullException(nameof(parameters));
//Create a list of the types in the dynamic[]
var inputParameterTypes = new Type[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
inputParameterTypes[i] = parameters[i].GetType();
}
const string NameOfMethod = nameof(Method); //This should be the name of your method which will be called
//Get every method from this class which has the name you are looking for
var methods = this.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(x => x.Name == NameOfMethod);
foreach (var method in methods)
{
//Get the parameters of the method
var methodParameters = method.GetParameters();
if (methodParameters.Length != inputParameterTypes.Length)
continue;
//Check if the types match with the input parameters
var match = true;
for (int i = 0; i < methodParameters.Length; i++)
{
//Check if the type matches
if (methodParameters[i].ParameterType == inputParameterTypes[i])
continue;
//Doesn't match
match = false;
}
if (!match)
continue;
//Call the method and return
method.Invoke(this, parameters);
return;
}
//If this is reached no valid methods were found
throw new Exception("No valid methods found!");
}
(此代码假定所有方法都在同一个类中)
使用此代码进行一些测量后:
var a = new Foo();
var parameters = new dynamic[][]
{
new dynamic[] { 1, "Test" },
new dynamic[] { 2 }
};
var sw = Stopwatch.StartNew();
for (int i = 0; i < Num; i++)
{
a.MethodOverload(parameters[i % 2]);
}
sw.Stop();
Console.WriteLine($"{Num} iterations took {sw.Elapsed.TotalMilliseconds} milliseconds. Average time: {sw.Elapsed.TotalMilliseconds / Num} milliseconds");
(从被调用函数中删除了 Console.WriteLine)
结果如下:
10000000 iterations took 5283.9398 milliseconds. Average time: 0.00052839398 milliseconds
100000000 iterations took 51244.9142 milliseconds. Average time: 0.000512449142 milliseconds
您需要使用Reflection并通过Invoke调用该方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.