1

I'm trying to understand the difference in variable declaration of a class inside or outside of a constructor. In this case creating the list for grades. To me, the below achieves the same result so which would be recommended and is there any reason why I should do one or the other? I have one way commented out and the other not.

class Book
{
    //List<double> grades;
    List<double> grades = new List<double>();
    public Book()
    {
        //Why not declare it here?
        //grades = new List<double>();
    }

    public void AddGrade(double grade)
    {
        grades.Add(grade);
    }
}
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Aiden
  • 179
  • 2
  • 13
  • The List is an instance variable. If you declare it in the constructor, it's a local variable which goes out of scope once the constructor exits. – R.J. Dunnill Aug 02 '19 at 21:34
  • 3
    @R.J.Dunnill Um no, that's not true at all. – DavidG Aug 02 '19 at 21:36
  • 1
    @R.J.Dunnill: Looking at the commented-out lines, I think OP means why not split the declaration from the initialization. – StriplingWarrior Aug 02 '19 at 21:36
  • This comes down to preference as it's quite opinion based. I like to do it in the constructor so I can see **when and what** gets instanciated/set. But again, there a other reasons for not doing it there e.g. less code in the constructor. If the fields aren't readonly you can also use another method to set them. I'm voting to close as primarly opinion based. – Joelius Aug 02 '19 at 21:36
  • Usually in constructor one initializes properties which depend on constructor parameters or require complicated computations. In this case I would go with out-of-constructor initialization, but I believe either way is considered OK. –  Aug 02 '19 at 21:37
  • 1
    The two methods you describe here are identical in terms of functionality. In practice, it's likely more important to be consistent rather than worry about anything else. – DavidG Aug 02 '19 at 21:37
  • @DavidG He's not declaring it; he's initializing it. – R.J. Dunnill Aug 02 '19 at 21:38
  • 1
    @R.J.Dunnill Yes, and your comment is flat out wrong. – DavidG Aug 02 '19 at 21:38
  • @StriplingWarrior Yes. – R.J. Dunnill Aug 02 '19 at 21:38
  • 1
    The biggest difference is when there are multiple constructors. Initializing a class member in one place can be nice. – Garr Godfrey Aug 02 '19 at 21:42
  • @DavidG The OP's code asked 'Why not declare it here?' I answered that. – R.J. Dunnill Aug 02 '19 at 21:42
  • 1
    @R.J.Dunnill Yes, and there is no declaration in the constructor, there is only initialisation so nothing is going out of scope. – DavidG Aug 02 '19 at 21:43
  • @GarrGodfrey multiple constructors and they are not chained. i.e. they all call `base(...)` with various overloads and there is no way to chain them. – Suiden Aug 02 '19 at 21:44
  • @DavidG My last word: again, the OP asked 'Why not declare it here?' – R.J. Dunnill Aug 02 '19 at 21:45
  • @R.J.Dunnill And look at the code, not the incorrect terminology used, OP is talking about initialisation, not declaration. – DavidG Aug 02 '19 at 21:46
  • 1
    @R.J.Dunnill: It's generally better to read between the lines and answer the _intended_ question rather than giving a technically-correct answer that misses the point. – StriplingWarrior Aug 02 '19 at 22:01

1 Answers1

3

There's a fair bit of room for personal opinion here, but in general terms:

  1. Declaring and initializing the field on the same line helps you to verify the field is initialized without needing to look in multiple places. If you see a field declared without an initializer, you have to look in a different part of code to see whether the item is being initialized at all.
  2. There are circumstances (like when the initial value is based on a constructor argument) when you cannot initialize the field inline. Since you will sometimes need to initialize fields in the constructor, some people will argue that it's more consistent to always initialize them there.

You may also want to ask: Should I be requiring/allowing an initial value to be provided in the constructor?

    class Book
    {
        readonly List<double> grades;
        public Book() : this(Array.Empty<double>())
        {
        }

        public Book(IEnumerable<double> grades)
        {
            this.grades = grades.ToList();
        }

        public void AddGrade(double grade)
        {
            grades.Add(grade);
        }
    }

And: should my class actually just be a dumb data container without a constructor or logic? (Is book.AddGrade(...) really more sensible than book.Grades.Add(...)?)

    class Book
    {
        public List<double> Grades {get;} = new List<double>();
    } 
StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315