When you use delegate:
public delegate T Sum<T>(T a, T b);
class Program
{
static void Main(string[] args)
{
int sum = Test.Sum(new[] {1, 2, 3}, (x, y) => x + y);
}
}
public static class Test
{
public static int Sum<T>(IEnumerable<T> sequence, Sum<T> summator)
{
// Do work
}
}
When you use an Interface:
public interface ISummator<T>
{
T Sum(T a, T b);
}
public class IntSummator : ISummator<int>
{
public int Sum(int a, int b)
{
return a + b;
}
}
class Program
{
static void Main(string[] args)
{
int sum = Test.Sum(new[] {1, 2, 3}, new IntSummator());
}
}
public static class Test
{
public static int Sum<T>(IEnumerable<T> sequence, ISummator<T> summator)
{
// Do work
}
}
Use case - provide a thing that can do only one action. Delegates are good because you don't have to create new classes you can just take a method with the same signature, or even pass a lambda which calls a method with different signature. But Interfaces are more flexible if you decide to get more complex logic:
public interface IArithmeticOperations<T>
{
T Sum(T a, T b);
T Sub(T a, T b);
T Div(T a, T b);
T Mult(T a, T b);
//
}
public class IntArithmetic : IArithmeticOperations<int>
{
public int Sum(int a, int b)
{
return a + b;
}
public int Sub(int a, int b)
{
return a - b;
}
public int Div(int a, int b)
{
return a / b;
}
public int Mult(int a, int b)
{
return a * b;
}
}
class Program
{
static void Main(string[] args)
{
int sum = Test.SumOfSquares(new[] {1, 2, 3}, new IntArithmetic());
}
}
public static class Test
{
public static int SumOfSquares<T>(IEnumerable<T> sequence, IArithmeticOperations<T> summator)
{
// Do work
}
}