如何在C#中创建以方法作为参数且参数数量不确定的方法?

问题描述 投票:1回答:3

我是C#的新手,有一个问题。我不确定是否曾有人问过这个问题或与之类似的问题,但是我找不到明确的解决方案。我已经在C#中创建了一个方法,它的参数是一个通用方法:

public void MyMethod (some_generic_method)

该“ some_generic_method”可能具有不同数量的具有同类数据类型的参数。如何创建“ MyMethod”的签名?

编辑:我将尝试尽可能清楚地解释为什么需要所要求的解决方案。我正在用C#创建一个测试库,该库包含一个类似于“ MyMethod”的方法。

想象:

  • 用户创建了一个具有几种不同方法的类,
  • 用户正在他/她的C#脚本中“使用”我的库,
  • 用户事先知道,要能够利用该库,他/她的方法名称必须包含一个特定的字符串(让我们假设“ test”),
  • 我的库“ MyMethod”应该查找那些包含“ test”作为其名称一部分的用户定义方法(在我的代码的相应部分中,我正在使用反射,汇编,类型,...和“ if( method.name包含“ test”)“,因此库可以检测到那些特定的方法,并将它们分别传递给其“ MyMethod”),
  • 现在,由于我们不知道那些用户定义的方法签名是什么样的,因此“ MyMethod”的参数应采用可以处理任何用户定义的方法的方式。这就是为什么在我的问题中我首先提到“ some_generic_method”(即“ MyMethod”参数)可能具有不同数量的同质/异质数据类型的参数的原因。

我希望这个解释使问题更清楚。

谢谢。

c# methods parameters
3个回答
1
投票

如果您做的时间足够长,您最终会发现自己反复编写此函数:

    public static Type3 CombineFunc1AndFunc2(
   Func<Type1, Type2> func1,
   Func<Type2, Type3>> func2,
   Type1 input)
    {
   return func2(func1(input))
   }

这样的包装函数在专门用于一种类型时没有太多用处。但是,如果引入一些类型变量并省略了输入参数,则GetFormattedRate定义如下所示:

public static Func<A, C> Compose(
   Func<B, C> outer, Func<A, B>> inner)
{
    return (input) => outer(inner(input))

}

var GetFormattedRate = Compose(FormatRate, GetRate);
var formattedRate = GetFormattedRate(rateKey);

就目前而言,您所做的没有什么目的。它不是通用的,因此您需要在各处复制该代码。它使您的代码过于复杂,因为现在您的代码必须自己组装来自千个微型函数的所有内容。不过,您的心在正确的地方:您只需要习惯使用这类通用的高阶函数将事物放在一起即可。或者,使用优质的老式Lambda将Func和A变成Func


0
投票

该“ some_generic_method”可能具有不同数量的具有同类数据类型的参数。

“均匀数据类型”限制很有帮助。我们可以使用单个类型参数定义新方法:

public void MyMethod<T>(...)

[不幸的是,我们无法用一种方法完全达到目标。对于每个受支持的类型参数,我们将需要重载:

public void MyMethod<T>(Func<T> arg) { ... }
public void MyMethod<T>(Func<T,T> arg) { ... }
public void MyMethod<T>(Func<T,T,T> arg) { ... } 
// etc

如果您查看框架源,这是平台设计人员自己必须为委托,元组和params参数所做的事情。

但是我想知道您是否可以调整以执行以下操作之一:

public void MyMethod<T>(Func<IEnumerable<T>,T> arg) { ... }
public void MyMethod<T>(Func<T[],T> arg) { ... } 

0
投票

考虑

据我所知,不知道其签名就不可能调用方法。

例如,在不像Javascript,Python或Ruby的C#中,签名是静态的,在编译后就明确定义,因此是不可变的。

即使使用对象的反射作为参数,您也将遇到相同的问题来管理具有未知类型的未知参数的此未知方法的参数。

C#是一种强类型语言,即使使用动态语言也是一种编译语言。

相反,C#泛型并不意味着未知的类型和签名,即使它们是祖先,它们也不是C ++模板。

params用于参数

https://docs.microsoft.com/dotnet/csharp/language-reference/keywords/params

public delegate void ParameterizedActionWithParams(params object[] parameters);

public void MyAction(ParameterizedActionWithParams action, params object[] parameters)
{
  if ( action != null )
    action(parameters);
  else
    ManageArgumentNullException();
}

使用对象列表

public delegate void ParameterizedActionWithList(List<object> parameters);

public void MyAction(ParameterizedActionWithList action, List<object> parameters)
{
  if ( action != null )
    action(parameters);
  else
    ManageArgumentNullException();
}

限制

您不能有强类型的参数。

如果您也需要函数,则返回的参数可能有所不同,您只能这样做:

public delegate object ParameterizedFuncWithParams(params object[] parameters);

public delegate object ParameterizedFuncWithList(List<object> parameters);

因此您需要创建以下变体:

public object MyFunc(ParameterizedFuncWithParams func, params object[] parameters)
{
  if ( func != null )
    return func(parameters);
  else
    ManageArgumentNullException();
}

public object MyFunc(ParameterizedFuncWithList func, List<object> parameters)
{
  if ( func != null )
    return func(parameters);
  else
    ManageArgumentNullException();
}
热门问题
推荐问题
最新问题