Skip to content

Commit 619af9b

Browse files
authored
Add AV1032: Consider a delegate instead of an interface with a single method (#312)
1 parent 6fc3b6d commit 619af9b

1 file changed

Lines changed: 39 additions & 0 deletions

File tree

_rules/1032.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
rule_id: 1032
3+
rule_category: class-design
4+
title: Consider a named delegate instead of an interface with a single method
5+
severity: 3
6+
---
7+
An interface with a single method is essentially a named function signature. Unless you know that this interface will gain more members in the near future, a delegate is simpler, creates a more loosely coupled abstraction, and you don't need mocking frameworks to provide a value in tests.
8+
9+
```csharp
10+
// Instead of this single-method interface...
11+
public interface IOrderFilter
12+
{
13+
bool Matches(Order order);
14+
}
15+
16+
// ...consider a delegate
17+
public delegate bool OrderFilter(Order order);
18+
19+
// Or simply use Func<T, bool>
20+
public void Process(IEnumerable<Order> orders, OrderFilter filter)
21+
{
22+
foreach (var order in orders.Where(filter))
23+
{
24+
// ...
25+
}
26+
}
27+
28+
// In a test you can pass any method or lambda that matches the signature.
29+
Process(orders, order => order.Value > 10000);
30+
```
31+
32+
Prefer a single-method interface when:
33+
- Implementations need to carry state
34+
- The interface is supposed to provide a strong well-defined contract like `IEquatable`, `IDisposable`
35+
- You want to use Default Interface Methods
36+
- The interface is expected to gain additional members in the near future
37+
38+
**Note:** A simple lambda is technically compatible with a named delegate, but a named delegate offers better discoverability: find-usages, go-to-definition, and DI registration all work the same as with an interface.
39+

0 commit comments

Comments
 (0)