I have a delegate which looks like the following:
public delegate bool ApprovalPrompt(ApprovalType type, int receipt, params string[] info);
I accept a delegate of this type as a parameter to the function I want to call. However, in one particular calling function, I want to pass some extra data to the function which matches this delegate.
Here's the signature of the implementing function:
private static bool LogApprovalNeeded(FraudFilterUtilities.ApprovalType type, int receipt, params string[] info)
and it's being called as follows:
PrepareReceipt(LogApprovalNeeded);
I'd like it to be:
private static bool LogApprovalNeeded(Customer cust, FraudFilterUtilities.ApprovalType type, int receipt, params string[] info)
which ideally would be used as follows:
PrepareReceipt(LogApprovalNeeded(myCustomer))
How can I accomplish such a thing? I'd rather not need to declare a field in the class just to hold the Customer
parameter between one function and the callback...
You can use a lambda to achieve what you need.
Alternatively, change your
LogApprovalNeeded
signature to:But it could get a bit confusing, considering that you already have a variable number of parameters defined after
cust
.EDIT: As Servy rightfully pointed out, the change of signature won't let you call the method as you described. If you move the logic related to
Customer
toPrepareReceipt
, though, you won't need to use the above approach (which basically generates a new anonymous method and wrapsmyCustomer
in a closure.You can change the
PrepareReceipt
function to take an additional parameter. The signature would look something likepublic void PrepareReceipt(Customer customer, ApprovalPrompt approvalPrompt)
to accomplish this.You can't pass it to that delegate as the delegate does not declare an argument of type Customer. The "simple answer" would be to change the signature of the delegate to take the new argument.
That said, that would also require modification of all the consumers of the delegate.
You can use a lambda to "curry" your function:
Currying a function is the formal term for storing a reference to a function but with one or more of the parameters "fixed", thus altering the signature of the method.
You can also use a lambda when the signature of your function doesn't need all of the arguments that the delegate is providing; you can effectively discard parameters by not passing forward all of the arguments in the lambda.
If you need generic solution for delegates partial application (parameters reduction) take a look to the NReco Commons open source library, it contains PartialDelegateAdapter that can do that for any delegate type:
in this example 1st parameter is fixed with myCustomer value. In addition it also tries to harmonize argument types in runtime.
Lamba methods aren't perfect: they don't have attributes and they contribute for a messy code.
If you want to avoid that kind of methods, you can do it in an alternative way, which is just like JavaScript's
.bind()
function.That function can adapted in C# as follow, using a static class with some extension method:
Now you can create a delegate for your method (not lambda) and assign to it some fixed parameters:
So, the below code will produce a
WaitCallback
delegate:Whereas the below code will produce a
Func<object, object>
delegate: