19

I have an abstract class and I'd like to initialize a readonly field in its protected constructor. I'd like this readonly field to be available in derived classes.

Following my habit of making all fields private and exposing properties, I implemented this as follows:

abstract class Foo
{
    private readonly int _field;

    protected Foo(int field)
    {
        _field = field;
    }

    protected int Field
    {
        get { return _field; }
    }
}

But then I wondered if there is really much advantage of keeping the field private here. I'm aware of the advantages of properties and there are several SO questions on this issue in general, but they focus on public fields as opposed to protected ones.

So should I switch to the below implementation or not? What are the considerations and advantages/disadvantages to be aware of in either case?

abstract class Foo
{
    protected readonly int _field;

    protected Foo(int field)
    {
        _field = field;
    }
}
Zaid Masud
  • 13,225
  • 9
  • 67
  • 88
  • 1
    There isn't really a difference between `public` and `protected` when considering this. Both a visible outside the declaring assembly. So pretty much every argument concerning `public readonly X Y` vs. `public X Y{get;}` applies. – CodesInChaos Oct 23 '12 at 11:25

7 Answers7

13

Derived classes are still 'users' of the original code; fields should be encapsulated from them too.

You should think of base classes as safe and extendable APIs, rather than just classes which expose their internals. Keep the fields private - apart from anything, it allows the base class to change how that property's value is generated :)

Lawrence Wagerfield
  • 6,471
  • 5
  • 42
  • 84
5

I'd leave the implementation or go with:

protected Field {get; private set;}

(not exactly the same as Field is not readonly for the parent class)

The advantage of properties over fields is they are more future proof. You can change the implementation on the parent class without affecting the children. Without the property you're committed to the field always being readonly. Using fields is frowned upon for another reason, they hurt opacity: the class describes the exact implementation of the field.

So yes, leave the encapsulation.

The only place where I would consider using fields directly for readability is in highly coupled classes such as the states in a state pattern, but in this case the classes themselves would be private.

Eli Algranti
  • 8,707
  • 2
  • 42
  • 50
1

Readonly properties were implemented in C# 6.0. This is as simple as:

protected Foo(int field)
{
    Field = field;
}

protected int Field { get; }
VladL
  • 12,769
  • 10
  • 63
  • 83
  • It can be set and modified only from the constructor, same as readonly field. It is not same as the proper with private set – VladL Nov 17 '16 at 21:03
1

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.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
0
abstract class Foo
{
    protected readonly int _field;

    protected Foo(int field)
    {
        _field = field;
    }
}

Will be appropriate as you want the derived class to be aware of it. Classes not of type Foo won't have access to _field.

Lews Therin
  • 10,907
  • 4
  • 48
  • 72
0

Using reflection you can overwrite the readonly field with ease. Using a property makes it harder because the field is hidden ( You can still do it ). So i would prefer a property which is anyway the cleaner because you can change the getter without any issues.

If you're thinking about performance: Properties are inlined most times.

Override readonly's

class Program
{
    static void Main(string[] args)
    {
        Test t = new Test();
        t.OverrideReadonly("TestField", 5);
        t.OverrideReadonly("TestField2", 6);
        t.OverrideReadonly("TestField3", new Test());
    }
}

class Test
{
    protected readonly Int32 TestField = 1;
    protected readonly Int32 TestField2 = 2;
    protected readonly Test TestField3 = null;

    public void OverrideReadonly(String fieldName, Object value)
    {
        FieldInfo field = typeof(Test).GetField(fieldName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        field.SetValue(this, value);
    }
}
Community
  • 1
  • 1
Felix K.
  • 6,201
  • 2
  • 38
  • 71
  • I don't doubt your assertion about overwriting readonly fields with reflection, but would be nice to see a reference or an example. The part I do doubt is that it can be done "*with ease*". – Zaid Masud Oct 23 '12 at 11:35
  • Thanks, but apparently a [private readonly field is just as easy to change](http://stackoverflow.com/questions/934930/can-i-change-a-private-readonly-field-in-c-sharp-using-reflection) – Zaid Masud Oct 23 '12 at 12:42
  • @ZaidMasud As i said, that's the reason for better using properties with a private setter. It's not so easy anymore to change the field then and it has some advantages when you want to change something in the getter ( i.e. if you replace the backing variable with code which retrieves a remote instance ). – Felix K. Oct 23 '12 at 13:19
  • My only point is that, using reflection, a private readonly field seems just as easy to change as a protected readonly field. – Zaid Masud Oct 23 '12 at 14:07
  • @ZaidMasud That's correct, but there is a little difference. As a inheritor you don't know if the field `MyPrivateField`'s name isn't changed at the next release of the software, so setting the field via reflection is error prone. If you use a protected readonly field you, as Software-Vendor, should keep the original field name because anything else would force all users of your software to recompile or even change the code using it. Anyway there is no way to prevent access, but at least you can make it as hard as possible and use a property which also allows you some code changes. – Felix K. Oct 23 '12 at 14:29
  • Without changing the variable into a property and force a recompile of all users. – Felix K. Oct 23 '12 at 14:30
-2

Using a private field and a protected getter has a slight advantage: you don't cause an additional level of indirection.

Don't forget the c# shorthand way of declaring properties:

protected int Field { protected get; private set; }
Destrictor
  • 752
  • 1
  • 4
  • 15
  • @ZaidMasud no, the private field would be the way OP was using it. I only added code to show the shorthand way, not the microoptimization :) – Destrictor Oct 23 '12 at 13:10