List or Dictionary of Objects inside Class

It mostly depends on your needs and your architectural/design preferences.

Having the dictionary inside your class makes all class-related logic nicely encapsulated. That way, you can hide the (static) dictionary from the class users and have it managed by your class internally.

Having the dictionary outside your class makes the mechanism flexible in other ways. You can manage multiple different dictionaries for your class instances (for multiple purposes), for instance. Or you can just leave such a dictionary away if you don't need it in a specific solution environment.

IMHO, there are no strict guidelines that tell you that you should or shouldn't do something specific. Just be creative. As long as the end result is clear, maintainable, extendable etc. the sky is the limit.


Well, A version means that you can't have two Table with a same ID.

using System.Collections.Concurrent;

...

public class Table {
  //DONE: Do not expose fields but readonly properties 
  //DONE: Keep static (i.e. global) members (fields, properties, methods) being thread safe
  private static ConcurrentDictionary<int, Table> s_Tables = 
    new ConcurrentDictionary<int, Table>();

  public Table(int ID) { 
    s_Tables.Add(ID, this);
  }

  //DONE: All we expose is thead safe read-only version of the dictionary
  public static IReadOnlyDictionary<int, Table> Tables = s_Tables;
}

When B version means that you can well have several Program each of them have their own Tables and that's why ID is not globaly unique:

public class Program {
  //DONE: Do not expose fields but readonly properties 
  private Dictionary<int,Table> m_Tables = new Dictionary<int, Table>();

  public Program() {
    Table A = new Table (10);
    m_Tables.Add(10,A); 

    ...
  }

  //DONE: All we expose is read-only version of the dictionary
  public IReadOnlyDictionary<int, Table> Tables = m_Tables; 
}

...

//DONE: please, do not cram all the logic into `Main`, 
//      have a special classes business logic (Program) and entry point
public static class EntryPoint {
  static void Main(string[] args) {
    Program program = new Program();

    ...
  }
}

Since in your original code you have static void Main in Program class it's efficiently singleton, so it seems, version A is preferable: all about Table are within Table class; you can't occasionaly create a second instance of Table with same ID