I can think of two reasons to prefer a protected property over a protected field. First, consider this example:
public class BaseClass
{
protected readonly List<string> _someValues;
}
public class InheritedClass : BaseClass
{
public void NeedsThoseValues()
{
DoSomethingWith(_someValues);
}
}
Now you decide to change the base class to use lazy instantiation:
public class BaseClass
{
protected readonly Lazy<List<string>> _someValues;
}
Now the inherited class(es) must change to call _someValues.Value
. Did those inherited classes really need to change? If field was private and exposed to the inherited classes as a property, changing the base class wouldn't break the inherited classes:
public class BaseClass
{
private readonly Lazy<List<string>> _someValues;
protected List<string> SomeValues => _someValues.Value;
}
This requires us to change the way we mentally picture inherited classes. We might start off visualizing it like building a larger house around a smaller house. Everything that was in the smaller house is in the larger house, so it's really all one big house. There's no reason to hide the inner house from the outer house.
In reality it's nothing like that. The base class is its own distinct entity which exists within the larger house. In order to reuse it within multiple houses (multiple inherited classes) we need to encapsulate it so that the inherited classes don't know any more than they need to about it, just like with any other classes they depend on.
This sometimes creates an odd relationship. We're trying to prevent excessive coupling between the inherited class and implementation details of the base class, and yet they are coupled, because the inherited class can't exist without the base class. That raises the question - why should the inherited class have that relationship with the base class at all? Why not separate what the base class does into its own class, represent it with an abstraction (like an interface) and inject that where it's needed?
That's the idea behind preferring composition over inheritance. Many, many times inheritance is used to share functionality between classes (the base and the child) when that's not what it's for. If we have two varying areas of functionality, we should accomplish that with two different classes, and one can depend on the other. If we achieve this through inheritance we're going to hit a snag when our class needs to depend on yet another class. We can't give it yet another base class. Unless we're composing distinct classes to work together we might start doing some really evil things like adding more functionality into the existing base classes or creating more levels of inheritance. It gets hard to understand and eventually paints us into a corner.
The other reason is that when someone sees _someValues
referenced in the base class they're going to assume that it's a field declared in the class where it's used since that's the more common convention. It's not going to create any huge confusion but it will take them a moment longer to figure it out.
These reasons for preferring protected readonly properties over protected readonly fields might not be a problem in many particular cases. But it's hard to know that up front, so it's a good idea to pick the preferred practice and just make a habit out of it while understanding why you're doing it.