DEV Community

Discussion on: No more NullReferenceException for Lists in C#

 
danstur profile image
danstur

But there is an important difference between null and empty and your solution peppers over a simple programmer error while hiding that difference.

C# is almost 20 years old by now and it and the whole world is moving towards non-nullability by default. C# 8 makes this easier than ever before.

There simply is no reason to write your code instead of simply doing

public sealed class Foo 
{
    public ICollection<int> SomeInts { get; } = new List<int>(); // there we go, never going to be null.
}

Why should the compiler special case lists? What about Dictionaries? Old StringCollections from the time before generics? What about stringbuilders or custom classes that implement ICollection? What if they don't have a no argument constructor?

A whole lot of complicated questions to answer for a problem for which best practices have existed for decades: Initialize your classes in such a way that all its properties have valid values.

Thread Thread
 
alialp profile image
Ali Alp

Your solution about initializing at object construction contradicting with your own stated argument regarding the difference between null and empty if you initialize the object at the construction you will loose the chance of determining whether the collection ever been used or not, also can cause overhead in some cases in grained memory management, all i'm saying is adding to a list and initializing it when it's null should happen at once and the developer should not be woried about the initializing it when they try to add to it , in c# 8 still you may define a nullable list, therefore the question will remain intact

Thread Thread
 
danstur profile image
danstur • Edited

Read again: What I said is that in some rare situations it makes sense to distinguish between empty and null collections. In almost all situations it does not.

And sure there are incredibly rare situations where the memory pressure of unnecessarily initialising a list will cause performance problems, but the 101 of performance is to first write clean, simple code and only when you actually have a problem profile and start optimising.

I take any bet that you've never come across a situation in your professional development life where that was actually a problem (and adding a branch to every single add of a list is quite awful from a performance point of view too).

And yes in C# 8 you can still define a nullable list, but best practice tells you that you should avoid nullability as much as possible.

But I mean if the fact that pretty much every single comment is negative to this idea and that it goes against best practices in modern C# and nobody else is doing this despite extension methods being around for years (I mean the whole "use extension method to be able to use instance methods on possibly null values" has been done to death - usually for things such as assertions, this is not novel in itself) convinces you this might not be the best idea, I doubt me going on about this will make a difference.

Thread Thread
 
alialp profile image
Ali Alp • Edited

I'm not claiming that the approach of this article is the best solution or following the best practices , just a demonstration of a prototype of a possible better approach. About writing simple and profiling , it depends on the application , simplicity and clean code are guidelines , not an approach , it always depends , you don't need to bet ,what i have faced in my career or you have is not relevant , the approach should be generic , can you think of any condition which you are adding an item to a collection but Don't want to initialize it ?
Because i don't think there is , therefore i believe the first addition should handle the initialization

Thread Thread
 
aaronincincy profile image
Aaron Johnson

I feel like you're being intentionally obtuse about this when everyone else has provided great arguments in favor of always-initializing collections.

To play your game, here's an example:


class LibraryVisitor {
  private List<Book> CheckedOutBooks { get; set; }
  private string MemberNumber { get; set; }

  public void CheckOut(Book book) {
    CheckedOutBooks.Add(book);
  }

  public void Register(memberNumber) {
    MemberNumber = memberNumber;
    CheckedOut = new List<Book>();
  }
}

This is obviously shit code (arguably no worse than your examples), but the premise is I shouldn't be able to check out a book until I've registered.

A reasonable fix to this code would be:


class LibraryVisitor {
  private List<Book> CheckedOutBooks { get; } = new List<Book>();
  private string MemberNumber { get; }

  public void CheckOut(Book book) {
    if (MemberNumber == null) {
      throw new NotRegisteredException();
    }

    CheckedOutBooks.Add(book);
  }

  public void Register(memberNumber) {
    MemberNumber = memberNumber;
  }
}
Thread Thread
 
alialp profile image
Ali Alp

When you don't get , you don't get it.
let me demistify once more.
The conventional methods which any junior developer should be aware are crystal clear . The issue is why when you are trying to add to a list which is a member of a class and you already instantiated the class should throw an exception ?
It should instanciate the list object on the first add itself.