views:

73

answers:

4

I'm a bit fuzzy on the new Action/Func/Variance/CoVariance stuff, which is probably what I need.

What I want is to be able to pass a delegate as a parameter to a method, that takes a string and returns a bool. The problem is that I can't use a typed delegate or interface since it will be used in different libraries which doesn't share libraries, and both will be invoked by a third.

So in general I want the delegate to be inferred by it's input and returning type.

So it'll be like:

delegate bool IncludeItemDelegate(string item);

ClassA.FetchItems(int someParameter,includeItemDelegate);
ClassB.FetchItems(int someParameter,string someOtherParam,includeItemDelegate);

Where A and B doesnt share any libraries, can it be done?

+6  A: 

How about Func<string,bool> ?

leppie
Ah, so that's how you use it, that was easy, thanks! :)
MattiasK
+6  A: 

Predicate is built-in and also signals intent:

ClassA.FetchItems(int someParameter, Predicate<string> filter);
Robert Jeppesen
Yes, this is nicer than Func<string, bool>.
Lunivore
Ah, a little more esoteric perhaps but seems to fit
MattiasK
+1  A: 

What you want is a Func:

aLibrary.ClassName.MethodName(new Func<string, bool>(myCallback));

Though your reasoning "I can't use a typed delegate or interface since it will be used in different libraries" is not 100% as you can just declare your typed delegate in the namespace of each library. FYI: Action is used when your callback method is void.

Update: Incidentally you neednt bother declaring your delegate in your caller as C# 3.0 (and above) will do it for you (the callback method's signature just needs to the same as expected by the method you are passing it from):

aLibrary.ClassName.MethodName(myCallbackMethod);
Mrk Mnl
Yeah, but now I can abstract the method itself for a interface for instance, and it'll be valid with the Func delegate parameter instead of a bunch of different typed delegates
MattiasK
Not nice. Duplicating the same delegate in different assemblies means client code can not send the same piece of code to different places, right?
Robert Jeppesen
No - all that matters is the method signature is the same - any caller will be able to pass their delegate to the library method so long as the signature is the same.
Mrk Mnl
Also you neednt bother declaring your delegate in your caller as C# 3.0 (and above) assumes it (again so long as the method signature is the same): aLibrary.ClassName.MethodName(myCallback);
Mrk Mnl
Incorrect, delegate types need to be the same.
Robert Jeppesen
This sample doesn't compile (rightfully so!) http://gist.github.com/646766
Robert Jeppesen
No you used an instance of a delegate in your example - my code just uses a method name...
Mrk Mnl
A: 

It's also possible to pass the Predicate as a lambda

class A
{
    static public IEnumerable<string> FetchItems(int max, Predicate<string> filter)
    {
        var l = new List<string>() {"test", "fest", "pest", "häst"};
        return l.FindAll(filter).Take(max);
    }
}

like this

var res = A.FetchItems(2, s => s.EndsWith("est"));
Jonas Elfström
ah, that's a nice bonus, thanks
MattiasK