-2

When I write a class in C#, I'm often not only using interface types in the public API/signatures, but also as types of the private members:

public class Foo {
    private readonly IDictionary<string, Bar> m_Bars; // <-- here

    public Foo() {
        m_Bars = new Dictionary<string, Bar>();
    }
}

There are some occasions when I don't do this, mostly when I need expose some ReadOnly interface variant of a mutable collection. Most common example would be having a List<T> I want to expose as IReadOnlyCollection<T> or IReadOnlyList<T>; I cannot make the member an ICollection<T> respectively IList<T> because those interfaces do not extend their IReadOnly counterparts to retain binary backwards compatibility and I'd have to add a wrapper to make it work:

public class Foo {
    private readonly List<Bar> m_Bars; // <-- not here

    public Foo() {
        m_Bars = new List<Bar>();
    }
    
    public IReadOnlyCollection<Bar> Bars => m_Bars;
}

Protected instance members are kind-of in the middle between private members and the public API, so the general benefits of exposing interfaces rather than classes do apply.

But for private members, does it help/hurt/make any difference? Does it for example introduce additional type checks every time the member is accessed?

LWChris
  • 3,320
  • 1
  • 22
  • 39
  • Private member can't be part of the interface. Not sure I understand, can you define your notion of interface? – vernou Aug 21 '20 at 20:46
  • I am asking whether it makes sense to define a private member as `IDictionary` instead of `Dictionary` for example. – LWChris Aug 21 '20 at 20:50
  • For a member over which you have complete control, such as `m_Bars` in the example, it's a matter of preference. Sometimes, the concrete type will have methods/properties not available on the interface, so you'll need to use the concrete type if you need those members, otherwise, it's whichever you want. – madreflection Aug 21 '20 at 21:02
  • One example for a helpful case: a constructor where someone passes in an initial `IDictionary` from the outside. With the private member being an interface, now your class isn't forced into supporting only the concrete `Dictionary` implementation anymore. (Though as @madreflection says, if your class depends on methods/properties not available on the interface, you'll need that concrete type anyway, so this is moot.) And admittedly, it feels low-value. – Sean Skelly Aug 21 '20 at 21:08
  • To the close voters: I don't see how asking about potential performance drawbacks or implications I don't see is "opinion based". Just because the answer turns out to be "it almost never matters enough to not go by preference" that doesn't mean the question was asking about opinions. – LWChris Aug 21 '20 at 22:06
  • My guess is that the close votes were cast because this question shows little research. Don't take it personally - in the old days of Stack Overflow it would have happily been accepted here and probably received detailed answers from C# experts like Jon Skeet or Eric Lippert - but today, with the sheer amount of garbage being posted as questions here and increasingly fewer eyes to weed out the good from the bad, it's far more likely for those eyes to err on the side of closing as opposed to leaving open (I have been guilty of this). Nothing you can do about it. – Ian Kemp Sep 01 '20 at 21:54

2 Answers2

1

[does it make] sense to define a private member as IDictionary<K, V> instead of Dictionary<K, V> for example?

There's a tiny overhead for an interface call, but it's not on an order of magnitude that's relevant for most scenarios. So let's assume there's no performance reason to favor the concrete class over the interface.

The benefit of using the more-derived class is that it has a richer API, eg

dictionary.Clear()

is simpler, and may outperform

var keysToRemove = dictionary.Keys.ToList();
foreach (var key in keysToRemove )
{
  dictionary.Remove(key);
}

or

dictonary = new Dictionary<TKey,TValue>();

The benefit of using the interface is that you never have to change code when later switching to a different IDicionary.

For a fully-encapsulated private member, the benefits are probably pretty low-value.

David Browne - Microsoft
  • 80,331
  • 6
  • 39
  • 67
0

It depends. If you create it in a constructor, you know what type it is already. When you use dependency injection it may make more sense to use interface, so your class can get instance of different classes and you don't have to change internal implementation. In your case with Dictionary, I would keep the type to be specific mostly because of performance, you can read more here

  • 1
    Thanks for the link, it's describing exactly the kind of additional work I was suspecting/wondering about when using an interface over a class. Of course, 2.6s for 100 million enumerations is not relevant for my case, but it's the kind of good-to-know knowledge I was after with my question. – LWChris Aug 21 '20 at 21:19