Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Best Practice: Using a delegate or an interface as a class dependency

I have a class that requires a way to retrieve a random integer value with a maximum. I don't want this class to depend on a specific way to retrieve that random value (such as system.random). Would it be best to:

(A) Use a public delegate (or func)

public delegate int NextRandomInt(int maxValue);

public class MyClass
{
    public NextRandomInt NextRandomInt { get; set; }

    public MyClass(NextRandomInt nextRandomInt)
    {
        NextRandomInt = nextRandomInt;
    }
}

(B) Use a public interface

public interface IRandomIntProvider
{
    int NextInt(int maxValue);
}

public class MyClass
{
    public IRandomIntProvider RandomIntProvider { get; set; }

    public MyClass(IRandomIntProvider randomIntProvider)
    {
        RandomIntProvider = randomIntProvider;
    }
}

(C) Something else all together.

Both ways work. I feel like using a delegate would be simpler and quicker to implement, but the interface is more readable and may be easier when dependency injection comes around.

like image 985
Josh Engler Avatar asked Apr 14 '16 15:04

Josh Engler


2 Answers

It depends as to how much job you want to implement using a delegate or an interface.

If your interface is going to have only one or even two methods, you could use a Func to force the same behavior. Otherwise i would use interfaces.

Mark Seemann explained just this pretty nicely here : link

To sum it up he states this:

Whenever possible, I prefer to model my APIs with delegates instead of one-method interfaces, since it gives me greater flexibility and less infrastructure code.

Obviously, this technique only works as long as you only need to abstract a single method. As soon as your abstraction needs a second method, you will need to introduce a proper interface or, preferably, an abstract base class.

like image 104
Nikola.Lukovic Avatar answered Nov 15 '22 00:11

Nikola.Lukovic


It's slightly hair-splitting, since either an interface or a delegate will work.

One reason to prefer the delegate in this case is that you're really only depending on a method, so it's a tiny bit redundant to have to declare both the interface and the method. If your process is anything like mine, the method name was obvious but the interface name wasn't, because it doesn't really mean anything. It's a container for the method. (And I would have ended up with almost the exact same name as you did.)

Also, a delegate gives you the option to use a static method. Your class still depends on an abstraction, so you can pass in a mocked method if needed for unit testing the class. I'm not usually a big fan of static methods, but that's largely because they interfere with testability. But if you're depending on a delegate rather than directly on the function then it doesn't matter.

like image 44
Scott Hannen Avatar answered Nov 14 '22 22:11

Scott Hannen