将通用方法作为参数传递给C# [英] Passing a generic method as a parameter in C#

查看:162
本文介绍了将通用方法作为参数传递给C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个函数,将另一个函数作为参数(并且稍后调用),我知道如果我知道函数的签名,但这是可能的,如果我不? (像在JavaScript中传递函数作为参数)



例如:

  //这应该接受任何类型的签名和返回值的函数
void DelayedCall(?functionToCallLater,float delayInSecs,params object [] values)
{
// here做一些事情(就像一个例子)
functionToCallLater.Invoke(values);
}

编辑:我不想假定关于 functionToCallLater 它可以像这样的例子:

  int MyFunc()
void MyFunc2 ()
void MyFunc3(int someParam)
string MyFunc4(int someParam,MyClass someOtherParam)
void MyFunc5< T>(params T [] values)


解决方案

你的意思是这样吗? :

  void DelayedCall< T>(Action< T> functionToCallLater,
float delayInSecs,params T [] values)
{
//这里做一些事情(就像一个例子)
functionToCallLater(values);
}

你有对象[]作为你的价值观,但我假设你想要使用泛型来指定它们的类型。另外,由于它看起来不像你调用的方法没有返回类型,所以我使用 Action< T> 而不是 Func<



根据下面的评论,



如果你想接受不同的签名,你真的有2个不同的选择。第一个像SLaks说的就是用反思。这可能会变得非常复杂,因为您将需要确定functionToCallLater中的参数的位置和类型,并将其与父函数中的传入参数进行对齐。有很多语义真的使这个困难(尽管是可能的),真的比麻烦更多,当问题被广泛地处理大量的情况。



处理这种情况的第二种和更可验证的方法(尽管不一定减少工作),是为有问题的方法创建重载:

  void DelayedCall< T>(Func< T> functionToCallLater,
float delayInSecs,params T [] values)

void DelayedCall< T,R>(Func< T,R> functionToCallLater,
float delayInSecs,params T [] values)

void DelayedCall< T(Func float delayInSecs,params T [] values)


取决于重载方法的复杂程度,这可能会很简单,几乎不可能,但它会奏效。在这种情况下,你想问自己的真正问题是,这是处理这种方法的最佳方式吗?例如,如果在调用方法中不需要返回值,为什么要允许一个?您可以随时强制调用者使用另一种遵守方法签名的方法来包装该功能:

  void DelayedCall< T> ;(Action< T> functionToCallLater,
float delayInSecs,params T [] values)
....
DelayledCallAction< int>(
(i)=> MyMethodWhichReturnsSomething i),
floadDelayInSecs,1,2,3);

这将删除方法需要处理的一些方案和功能。通过减少方法签名需要处理的可能选项,问题变得更简单和更易于管理。


I am trying to write a function, that takes another function as a parameter (and the calls it later) I know that its doable if I know the signature of the function beforehand, but is this possible, if I dont? (like passing a function as a parameter in JavaScript)

For example:

// this should accept a function with any kind of signature and return value
void DelayedCall(?? functionToCallLater, float delayInSecs, params object[] values)
{
    //here do something like (just as an example)
    functionToCallLater.Invoke(values);
}

EDIT: I do not want to assume anything about functionToCallLater It can look like these for example:

    int MyFunc()
    void MyFunc2()
    void MyFunc3(int someParam) 
    string MyFunc4(int someParam, MyClass someOtherParam) 
    void MyFunc5<T>(params T[] values) 

解决方案

Do you mean like this? :

void DelayedCall<T>(Action<T> functionToCallLater, 
  float delayInSecs, params T[] values)
{
    //here do something like (just as an example)
    functionToCallLater(values);
}

You have object[] as your values, but I'm assuming that you want to specify their type as well using a generic. Also, since it didn't look like your method you are calling doesn't have a return type, I used Action<T> instead of Func<T>.

Based on the comment below,

If you want to accept different signatures, you really have 2 different options. The first like SLaks said is to use reflection. This can get extremely complicated though, as you're going to have to determine the position and types of the parameters in the functionToCallLater, and line those up with the incoming parameters from the parent function. There are a lot of semantics that really make this difficult (although it is possible) and really more trouble than it's worse when the problem is generalized to handle a large number of cases.

A second and more verifiable way of handling this scenario (although not necessarily less work), is to create overloads for the method in question:

void DelayedCall<T>(Func<T> functionToCallLater, 
      float delayInSecs, params T[] values)

void DelayedCall<T,R>(Func<T,R> functionToCallLater, 
      float delayInSecs, params T[] values)

void DelayedCall<T>(Func<T,X,R> functionToCallLater, 
      float delayInSecs, params T[] values)

etc.

Depending on how complicated the method to overload is, this may be slightly tedious to almost impossible, but it will work. The real question you want to ask yourself in this scenario is, "Is this the optimal way to handle this approach?" For example, if you don't need a return value in the calling method, why allow one at all? You can always force the caller to wrap the function in another method which adheres to the method signature like so:

void DelayedCall<T>(Action<T> functionToCallLater, 
      float delayInSecs, params T[] values)
....
 DelayledCallAction<int>(
    (i) => MyMethodWhichReturnsSomething(i), 
    floadDelayInSecs, 1,2,3);

This removes some of the scenarios and functionality the method needs to handle. By reducing the possible options the method signature needs to handle, the problem becomes simpler and more manageable.

这篇关于将通用方法作为参数传递给C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆