9

I have been writing C# code for 10 years, but I am woefully weak on knowing exactly when to use an interface vs. using a Func or Action. It seems to me that in many places where a method on an interface is called, a Func or Action would work just as well. So, I guess my question is this. If I have an interface with just a single method, or perhaps a couple methods, is there any disadvantage to using a Func or Action instead? Using a Func or Action seems cleaner to me.

Thanks very much.

Randy Minder
  • 47,200
  • 49
  • 204
  • 358
  • 2
    Perhaps you may get your question across a bit more cleanly with a simple example as well where you would question which of the two to use. – deepee1 Oct 31 '12 at 14:11
  • I think i covered when you would have best use of them. They're like a container of different classes which all share some common functionality (with different implementations) – Shark Oct 31 '12 at 14:12
  • 1
    @deepee1 - I think the question is clear enough. If I clutter the question with code, people might tend to glaze over the whole thing. – Randy Minder Oct 31 '12 at 14:20
  • possible duplicate of [delegates-vs-interfaces-in-c-sharp](http://stackoverflow.com/questions/8694921/delegates-vs-interfaces-in-c-sharp) – nawfal Jul 03 '14 at 12:31

4 Answers4

7

I guess you can compare an Action or Func with an interface containing one method, with the difference that you can supply any Action or Func that meets the parameter / return value requirements, where when using interfaces, the supplied object must implement that interface.

Perhaps you could call Action and Func "anonymous single method interfaces".

If you look at the design perspective though, your class model would be a drawing of blocks without any lines between them.

C.Evenhuis
  • 25,996
  • 2
  • 58
  • 72
  • 2
    The Action/Func way is similar to how interfaces in Go are handled. It enables two modules to effectively having no common dependency (except for the parameter type). Not that I would recommend Action/Func in every situation. – Sebastian Graf Oct 31 '12 at 14:26
4

You should use delegates and lambda expressions if the implementations are expected to be very short (one or two lines), and especially if the implementations are expected to need local variables (closures).

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
4

I have to admit, I was a bit confused by this question. Like @deepee, I agree that a code example would have been good here to show why you think you would use one approach over the other.

The reason for my confusion is that I wouldn't have thought to ask this question since they serve different purposes. Interfaces are used mainly for polymorphism; so that one can treat different implementations all in the same way.

Jon Skeet has a good example of using Func and Action.

Interfaces allow you to do this:

IAnimal animal = AnimalFactory.GetAnimal();
animal.Run();

Using the above code, you don't know or care what kind of animal it is. You just know it can run and you want it to run. More importantly, the caller doesn't know how the animal runs. That's the difference between an Action and interfaces/polymorphism. The logic for doing something is in the concrete class.

An Action will allow you to do the same thing for each instance, when the actual logic is known by the caller, instead of having each concrete instance do something:

animals.ForEach(x => x.Run());

Or:

animals.ForEach(x => /* do something completely different here */);

The above line of code is action that only the caller decides what should happen, instead of delegating the logic to the actual instance by simply calling a method on it.

They solve different problems, so I'm curious to see how folks think they're interchangeable in certain situations.

Community
  • 1
  • 1
Bob Horn
  • 33,387
  • 34
  • 113
  • 219
  • Thank you. Couldn't different implementations be handled just as effectively by encapsulating the implementation in a Func, instead of an interface method, at least in some cases? Then, instead of the interface method being called, the Func is executed. – Randy Minder Oct 31 '12 at 14:50
  • 1
    Who is the information expert, the caller or the polymorphic concrete instance? If each concrete instance of an interface has its own logic, a func won't work because that's defined *outside* the concrete instance. If the logic is known by the caller, sure, a func could work. – Bob Horn Oct 31 '12 at 14:53
  • 1
    What you have shown is an example of an interface with multiple methods. If `IAnimal` has nothing other than `public void Run()` it doesn't really do any good. It doesn't return anything, and if `Run` has side effects they aren't visible. `IAnimal` would be useful because it causes side effects visible through other methods, such as a `Position` or `Stamina`. Delegates only really ever replace interfaces that would have a single method. – Servy Oct 31 '12 at 14:58
  • +1 for keeping with the Animal theme and putting to words what I left in code :) – Shark Oct 31 '12 at 15:00
1

You would use an Interface when you don't really care what kind of object you're working with...

Let's go with the textbook example

public class Animal;

public class Dog : Animal, IRunningAnimal { }
public class Cheetah : Animal, IRunningAnimal { }
public class Fish : Animal, ISwimmingAnimal { }
public class Gator : Animal, ISwimmingAnimal, IRunningAnimal { }

public interface IRunningAnimal 
{
    public void Run();
}

public interface ISwimmingAnimal
{
    public void Swim();
}

public abstract class Animal
{
    /// ...
    public abstract void Move();
}

then somewhere in code...

RunningAnimal runner = getAnimal();
//make him run
runner.Run();

each running animal might run in a different way but they all can run.

or better

if(getAnimal() instanceof RunningAnimal) getAnimal().Run();
else getAnimal().Move();
Fred
  • 12,086
  • 7
  • 60
  • 83
Shark
  • 6,513
  • 3
  • 28
  • 50
  • I guess you picked the wrong book. Question is tagged as `C#` :) – L.B Oct 31 '12 at 14:12
  • .... yep, just noticed it. On the other hand, I'll learn the difference between java and c# interfaces :) – Shark Oct 31 '12 at 14:15
  • Straight from a Java programming book? :) – Randy Minder Oct 31 '12 at 14:17
  • Nope, haven't wrote any programming books yet :) I just remember all those examples ran somewhere along these lines... i thought this was a java question :D – Shark Oct 31 '12 at 14:19
  • 4
    that last snippet of code is terrible. You should never need to do if/switches based on what type of object things are. In this scenario you should simply have a method called along the lines of "moveQuickly()" and then if the animal can run, he calls run() internally, otherwise it can default to a move(). – mike Oct 31 '12 at 14:21
  • @mrnye i know i know i was gonna edit it but by that time i already noticed this answer is effed up... so i just stopped bothering. – Shark Oct 31 '12 at 14:23
  • no problem, it's all a bit irrelevant to the question anyway – mike Oct 31 '12 at 14:24
  • in any case, i think this demonstrates the idea behind interfaces (in Java) ... i'm keen to see if they have a different use in C# mainly because i don't know C# at all (but i understand it when i read it :D) – Shark Oct 31 '12 at 14:26
  • 1
    @Shark Interfaces do the same thing in C# that they do in java. Delegates can be though of as a subset of the applications of an interface, and that is the "command pattern". Anything that could be implemented with delegates could be implemented instead with an interface model, the interface model just takes more code to do it. Delegates are a convenience mechanism, you never *need* them, they just make things easier. Just like properties are the same as lots of getters and setters, they just take less code to do it, but that doesn't mean that properties will replace all *methods*. – Servy Oct 31 '12 at 14:55
  • Someone edited my answer; what used to be `public class Dog extends Animal implements RunningAnimal` now became `public class Dog extends Animal, RunningAnimal` which employs multiple-inheritance. @Fred feel free to chip in. – Shark Mar 10 '16 at 15:33