简体   繁体   English

在C#中将通用方法作为参数传递

[英]Passing a generic method as a parameter in C#

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) (例如,将函数作为参数传递给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: 编辑:我不想承担有关functionToCallLater任何事情,例如,它们可能看起来像这样:

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

If you don't know anything about the function, you'll need to use Reflection (and pay a performance penalty). 如果您对该功能一无所知,则需要使用Reflection(并支付性能损失)。

Make it accept Delegate , then call .DynamicInvoke() . 使它接受Delegate ,然后调用.DynamicInvoke()

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. 您有object []作为值,但是我假设您也想使用泛型来指定它们的类型。 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> . 另外,由于看起来好像您要调用的方法没有返回类型,所以我使用Action<T>代替Func<T>

Based on the comment below, 根据以下评论,

If you want to accept different signatures, you really have 2 different options. 如果要接受不同的签名,则实际上有2个不同的选项。 The first like SLaks said is to use reflection. 像SLaks所说的第一个是使用反射。 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. 但是,这可能变得非常复杂,因为您将不得不确定functionToCallLater中参数的位置和类型,并将其与父函数的传入参数对齐。 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. 通过减少方法签名需要处理的可能选项,问题将变得更简单,更易于管理。

I think this would be probihitely verbose in C# :/ 我认为这在C#中可能是冗长的:/

Heres a solution that can accept a function that returns or does not return a value and accepts 0 - 2 parameters: 这是一个可以接受返回或不返回值并接受0-2参数的函数的解决方案:

    // signature: void MyFunc()
    void DelayedCall(Action sdf, float delayInSecs)
    {
    }

    // signature: SomeClass MyFunc()
    void DelayedCall<T>(Func<T> sdf, float delayInSecs)
    {
    }

    // signature: void MyFunc(SomeClass param1)
    void DelayedCall<T>(Action<T> sdf, float delayInSecs, T values)
    {
    }

    // signature: SomeClass MyFunc(SomeClass param1)
    void DelayedCall<T, K>(Func<T, K> sdf, float delayInSecs, T values)
    {
    }

    // signature: void MyFunc(SomeClass param1, SomeClass2 param2)
    void DelayedCall<T, K>(Action<T, K> sdf, float delayInSecs, T values, K values2)
    {
    }

    // signature: SomeClass MyFunc(SomeClass param1, SomeClass2 param2)
    void DelayedCall<T, K, L>(Func<T, K, L> sdf, float delayInSecs, T values, K values2)
    {
    }

These accept for example the following: 例如,它们接受以下内容:

    void MyFunc1() {  }
    int MyFunc2() { return 6; }
    void MyFunc3(int someParam) { }
    string MyFunc4(string someParam) { return "";  }
    void MyFunc5(int someParam, string someparam2) { }
    string MyFunc6(string someParam, int someparam2) { return "";  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM