List or Dictionary of Objects inside Class
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
A friend and I (both new in programming) were arguing if it was wise to include a Dictionary inside a Class that contains all instances of that class.
I say that is better that the dictionary is in the main instead in the class itself.
I have no strong reasons to say why , but i've never seen classes keeping records of the objects that has created.
Could you give me pros and cons of each approach?
Thanks in advance.
A:
class Table
{
public static Dictionary<int,Table> Tables = new Dictionary<int, Table>();
...
public table (int ID) // constructor
{
...
Tables.Add(ID,this);
}
}
B:
class Program
{
public Dictionary<int,Table> Tables = new Dictionary<int, Table>();
static void Main(string args)
{
...
Table A = new Table (10);
Tables.Add(10,A);
}
}
c#
add a comment |
A friend and I (both new in programming) were arguing if it was wise to include a Dictionary inside a Class that contains all instances of that class.
I say that is better that the dictionary is in the main instead in the class itself.
I have no strong reasons to say why , but i've never seen classes keeping records of the objects that has created.
Could you give me pros and cons of each approach?
Thanks in advance.
A:
class Table
{
public static Dictionary<int,Table> Tables = new Dictionary<int, Table>();
...
public table (int ID) // constructor
{
...
Tables.Add(ID,this);
}
}
B:
class Program
{
public Dictionary<int,Table> Tables = new Dictionary<int, Table>();
static void Main(string args)
{
...
Table A = new Table (10);
Tables.Add(10,A);
}
}
c#
Side note: do not expose fields but readonly properties: what if I assignnulltoTables? E.g.Table.Tables = null;
– Dmitry Bychenko
1 hour ago
@DmitryBychenko readonly is not good enough for this because you can still call any method from the Dictionary. The proper way to do this is to make it private and only interact with it using class methods.
– Chris Rollins
1 hour ago
1
@Chris Rollins: sure; at least exposeTablesasIReadOnlyDictionary<int, Table>readonly property.
– Dmitry Bychenko
1 hour ago
@DmitryBychenko that's a clever approach
– Chris Rollins
1 hour ago
1
Have you considered usingMemoryCacheinstead?
– mjwills
1 hour ago
add a comment |
A friend and I (both new in programming) were arguing if it was wise to include a Dictionary inside a Class that contains all instances of that class.
I say that is better that the dictionary is in the main instead in the class itself.
I have no strong reasons to say why , but i've never seen classes keeping records of the objects that has created.
Could you give me pros and cons of each approach?
Thanks in advance.
A:
class Table
{
public static Dictionary<int,Table> Tables = new Dictionary<int, Table>();
...
public table (int ID) // constructor
{
...
Tables.Add(ID,this);
}
}
B:
class Program
{
public Dictionary<int,Table> Tables = new Dictionary<int, Table>();
static void Main(string args)
{
...
Table A = new Table (10);
Tables.Add(10,A);
}
}
c#
A friend and I (both new in programming) were arguing if it was wise to include a Dictionary inside a Class that contains all instances of that class.
I say that is better that the dictionary is in the main instead in the class itself.
I have no strong reasons to say why , but i've never seen classes keeping records of the objects that has created.
Could you give me pros and cons of each approach?
Thanks in advance.
A:
class Table
{
public static Dictionary<int,Table> Tables = new Dictionary<int, Table>();
...
public table (int ID) // constructor
{
...
Tables.Add(ID,this);
}
}
B:
class Program
{
public Dictionary<int,Table> Tables = new Dictionary<int, Table>();
static void Main(string args)
{
...
Table A = new Table (10);
Tables.Add(10,A);
}
}
c#
c#
asked 2 hours ago
Mariano ValenzuelaMariano Valenzuela
4815
4815
Side note: do not expose fields but readonly properties: what if I assignnulltoTables? E.g.Table.Tables = null;
– Dmitry Bychenko
1 hour ago
@DmitryBychenko readonly is not good enough for this because you can still call any method from the Dictionary. The proper way to do this is to make it private and only interact with it using class methods.
– Chris Rollins
1 hour ago
1
@Chris Rollins: sure; at least exposeTablesasIReadOnlyDictionary<int, Table>readonly property.
– Dmitry Bychenko
1 hour ago
@DmitryBychenko that's a clever approach
– Chris Rollins
1 hour ago
1
Have you considered usingMemoryCacheinstead?
– mjwills
1 hour ago
add a comment |
Side note: do not expose fields but readonly properties: what if I assignnulltoTables? E.g.Table.Tables = null;
– Dmitry Bychenko
1 hour ago
@DmitryBychenko readonly is not good enough for this because you can still call any method from the Dictionary. The proper way to do this is to make it private and only interact with it using class methods.
– Chris Rollins
1 hour ago
1
@Chris Rollins: sure; at least exposeTablesasIReadOnlyDictionary<int, Table>readonly property.
– Dmitry Bychenko
1 hour ago
@DmitryBychenko that's a clever approach
– Chris Rollins
1 hour ago
1
Have you considered usingMemoryCacheinstead?
– mjwills
1 hour ago
Side note: do not expose fields but readonly properties: what if I assign
null to Tables? E.g. Table.Tables = null;– Dmitry Bychenko
1 hour ago
Side note: do not expose fields but readonly properties: what if I assign
null to Tables? E.g. Table.Tables = null;– Dmitry Bychenko
1 hour ago
@DmitryBychenko readonly is not good enough for this because you can still call any method from the Dictionary. The proper way to do this is to make it private and only interact with it using class methods.
– Chris Rollins
1 hour ago
@DmitryBychenko readonly is not good enough for this because you can still call any method from the Dictionary. The proper way to do this is to make it private and only interact with it using class methods.
– Chris Rollins
1 hour ago
1
1
@Chris Rollins: sure; at least expose
Tables as IReadOnlyDictionary<int, Table> readonly property.– Dmitry Bychenko
1 hour ago
@Chris Rollins: sure; at least expose
Tables as IReadOnlyDictionary<int, Table> readonly property.– Dmitry Bychenko
1 hour ago
@DmitryBychenko that's a clever approach
– Chris Rollins
1 hour ago
@DmitryBychenko that's a clever approach
– Chris Rollins
1 hour ago
1
1
Have you considered using
MemoryCache instead?– mjwills
1 hour ago
Have you considered using
MemoryCache instead?– mjwills
1 hour ago
add a comment |
5 Answers
5
active
oldest
votes
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.
add a comment |
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
add a comment |
Approach A. If all instances of a class should be tracked then it should be an automatic feature of the class which can be implemented using a static dictionary. The dictionary should be private so that other classes cannot modify it. This gives you a guarantee that the dictionary will be correct.
However, this is not a good technique for beginner programmers because it prevents the objects from being cleaned up by garbage collection. This means you have to manually decide when the objects should be released, at which time you remove them from the dictionary. You could implement the iDisposable interface for this. Usually it's best to use a using block with it, but sometimes you will need to find another way to manage the lifetime of the objects.
Approach B is fine for a small program, but it does not have any advantages either. In a larger program it will be hard to manage and prone to mistakes. You may forget to add an object, or you may have some code incorrectly add or remove an object, or some code may assume an object is there when it was removed, etc...
add a comment |
It's nothing wrong with any concepts. You have to decide whether caching is part of the design (A) or is an option of a consumer layer (B).
If it is a built-in feature I would slightly modify approach A:
public class Table
{
// cache is private so it cannot be manipulated from outside
private static Dictionary<int,Table> tables = new Dictionary<int, Table>();
// constructor is private so Table can be created by the GetTable factory method
private Table(int id)
{
//...
}
// the factory method that transparently returns the table either from cache or by creating one
public static Table GetTable(int id)
{
if (tables.TryGetValue(id, out Table result))
return result;
result = new Table(id);
tables[id] = result;
return result;
}
}
1
The next step is to maketablesbeing thread safe (e.g. with a help ofConcurrentDictionary<int, Table>)
– Dmitry Bychenko
1 hour ago
Yes, if the real-life scenario demands it, it can be polished. In that case theConcurrentDictionary<int, Table>.GetOrAddmethod can be used instead ofTryGetValue. Or, if the loader delegate must be protected as well, maybe a simple locking dictionary is a better option.
– taffer
1 hour ago
add a comment |
A:
pros: none
cons:
it is not the responsibility of class to track its instances (see SRP)
non-thread-safe (see ConcurrentDictionary)
B:
pros:
- class is not burdened excess responsibilities that out its scope
cons:
- 'tracking'-code should be encapsulated to separate class that be responsible for creating instances, tracking them, managing time life strategy, etc (factory may fit for that)
- non-thread-safe
As mentioned above If you need to cache some items then use the MemoryCache.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55898506%2flist-or-dictionary-of-objects-inside-class%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
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.
add a comment |
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.
add a comment |
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.
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.
answered 1 hour ago
Bart HoflandBart Hofland
77249
77249
add a comment |
add a comment |
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
add a comment |
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
add a comment |
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
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
edited 1 hour ago
answered 1 hour ago
Dmitry BychenkoDmitry Bychenko
113k10100142
113k10100142
add a comment |
add a comment |
Approach A. If all instances of a class should be tracked then it should be an automatic feature of the class which can be implemented using a static dictionary. The dictionary should be private so that other classes cannot modify it. This gives you a guarantee that the dictionary will be correct.
However, this is not a good technique for beginner programmers because it prevents the objects from being cleaned up by garbage collection. This means you have to manually decide when the objects should be released, at which time you remove them from the dictionary. You could implement the iDisposable interface for this. Usually it's best to use a using block with it, but sometimes you will need to find another way to manage the lifetime of the objects.
Approach B is fine for a small program, but it does not have any advantages either. In a larger program it will be hard to manage and prone to mistakes. You may forget to add an object, or you may have some code incorrectly add or remove an object, or some code may assume an object is there when it was removed, etc...
add a comment |
Approach A. If all instances of a class should be tracked then it should be an automatic feature of the class which can be implemented using a static dictionary. The dictionary should be private so that other classes cannot modify it. This gives you a guarantee that the dictionary will be correct.
However, this is not a good technique for beginner programmers because it prevents the objects from being cleaned up by garbage collection. This means you have to manually decide when the objects should be released, at which time you remove them from the dictionary. You could implement the iDisposable interface for this. Usually it's best to use a using block with it, but sometimes you will need to find another way to manage the lifetime of the objects.
Approach B is fine for a small program, but it does not have any advantages either. In a larger program it will be hard to manage and prone to mistakes. You may forget to add an object, or you may have some code incorrectly add or remove an object, or some code may assume an object is there when it was removed, etc...
add a comment |
Approach A. If all instances of a class should be tracked then it should be an automatic feature of the class which can be implemented using a static dictionary. The dictionary should be private so that other classes cannot modify it. This gives you a guarantee that the dictionary will be correct.
However, this is not a good technique for beginner programmers because it prevents the objects from being cleaned up by garbage collection. This means you have to manually decide when the objects should be released, at which time you remove them from the dictionary. You could implement the iDisposable interface for this. Usually it's best to use a using block with it, but sometimes you will need to find another way to manage the lifetime of the objects.
Approach B is fine for a small program, but it does not have any advantages either. In a larger program it will be hard to manage and prone to mistakes. You may forget to add an object, or you may have some code incorrectly add or remove an object, or some code may assume an object is there when it was removed, etc...
Approach A. If all instances of a class should be tracked then it should be an automatic feature of the class which can be implemented using a static dictionary. The dictionary should be private so that other classes cannot modify it. This gives you a guarantee that the dictionary will be correct.
However, this is not a good technique for beginner programmers because it prevents the objects from being cleaned up by garbage collection. This means you have to manually decide when the objects should be released, at which time you remove them from the dictionary. You could implement the iDisposable interface for this. Usually it's best to use a using block with it, but sometimes you will need to find another way to manage the lifetime of the objects.
Approach B is fine for a small program, but it does not have any advantages either. In a larger program it will be hard to manage and prone to mistakes. You may forget to add an object, or you may have some code incorrectly add or remove an object, or some code may assume an object is there when it was removed, etc...
answered 1 hour ago
Chris RollinsChris Rollins
31228
31228
add a comment |
add a comment |
It's nothing wrong with any concepts. You have to decide whether caching is part of the design (A) or is an option of a consumer layer (B).
If it is a built-in feature I would slightly modify approach A:
public class Table
{
// cache is private so it cannot be manipulated from outside
private static Dictionary<int,Table> tables = new Dictionary<int, Table>();
// constructor is private so Table can be created by the GetTable factory method
private Table(int id)
{
//...
}
// the factory method that transparently returns the table either from cache or by creating one
public static Table GetTable(int id)
{
if (tables.TryGetValue(id, out Table result))
return result;
result = new Table(id);
tables[id] = result;
return result;
}
}
1
The next step is to maketablesbeing thread safe (e.g. with a help ofConcurrentDictionary<int, Table>)
– Dmitry Bychenko
1 hour ago
Yes, if the real-life scenario demands it, it can be polished. In that case theConcurrentDictionary<int, Table>.GetOrAddmethod can be used instead ofTryGetValue. Or, if the loader delegate must be protected as well, maybe a simple locking dictionary is a better option.
– taffer
1 hour ago
add a comment |
It's nothing wrong with any concepts. You have to decide whether caching is part of the design (A) or is an option of a consumer layer (B).
If it is a built-in feature I would slightly modify approach A:
public class Table
{
// cache is private so it cannot be manipulated from outside
private static Dictionary<int,Table> tables = new Dictionary<int, Table>();
// constructor is private so Table can be created by the GetTable factory method
private Table(int id)
{
//...
}
// the factory method that transparently returns the table either from cache or by creating one
public static Table GetTable(int id)
{
if (tables.TryGetValue(id, out Table result))
return result;
result = new Table(id);
tables[id] = result;
return result;
}
}
1
The next step is to maketablesbeing thread safe (e.g. with a help ofConcurrentDictionary<int, Table>)
– Dmitry Bychenko
1 hour ago
Yes, if the real-life scenario demands it, it can be polished. In that case theConcurrentDictionary<int, Table>.GetOrAddmethod can be used instead ofTryGetValue. Or, if the loader delegate must be protected as well, maybe a simple locking dictionary is a better option.
– taffer
1 hour ago
add a comment |
It's nothing wrong with any concepts. You have to decide whether caching is part of the design (A) or is an option of a consumer layer (B).
If it is a built-in feature I would slightly modify approach A:
public class Table
{
// cache is private so it cannot be manipulated from outside
private static Dictionary<int,Table> tables = new Dictionary<int, Table>();
// constructor is private so Table can be created by the GetTable factory method
private Table(int id)
{
//...
}
// the factory method that transparently returns the table either from cache or by creating one
public static Table GetTable(int id)
{
if (tables.TryGetValue(id, out Table result))
return result;
result = new Table(id);
tables[id] = result;
return result;
}
}
It's nothing wrong with any concepts. You have to decide whether caching is part of the design (A) or is an option of a consumer layer (B).
If it is a built-in feature I would slightly modify approach A:
public class Table
{
// cache is private so it cannot be manipulated from outside
private static Dictionary<int,Table> tables = new Dictionary<int, Table>();
// constructor is private so Table can be created by the GetTable factory method
private Table(int id)
{
//...
}
// the factory method that transparently returns the table either from cache or by creating one
public static Table GetTable(int id)
{
if (tables.TryGetValue(id, out Table result))
return result;
result = new Table(id);
tables[id] = result;
return result;
}
}
answered 1 hour ago
taffertaffer
8,81121536
8,81121536
1
The next step is to maketablesbeing thread safe (e.g. with a help ofConcurrentDictionary<int, Table>)
– Dmitry Bychenko
1 hour ago
Yes, if the real-life scenario demands it, it can be polished. In that case theConcurrentDictionary<int, Table>.GetOrAddmethod can be used instead ofTryGetValue. Or, if the loader delegate must be protected as well, maybe a simple locking dictionary is a better option.
– taffer
1 hour ago
add a comment |
1
The next step is to maketablesbeing thread safe (e.g. with a help ofConcurrentDictionary<int, Table>)
– Dmitry Bychenko
1 hour ago
Yes, if the real-life scenario demands it, it can be polished. In that case theConcurrentDictionary<int, Table>.GetOrAddmethod can be used instead ofTryGetValue. Or, if the loader delegate must be protected as well, maybe a simple locking dictionary is a better option.
– taffer
1 hour ago
1
1
The next step is to make
tables being thread safe (e.g. with a help of ConcurrentDictionary<int, Table>)– Dmitry Bychenko
1 hour ago
The next step is to make
tables being thread safe (e.g. with a help of ConcurrentDictionary<int, Table>)– Dmitry Bychenko
1 hour ago
Yes, if the real-life scenario demands it, it can be polished. In that case the
ConcurrentDictionary<int, Table>.GetOrAdd method can be used instead of TryGetValue. Or, if the loader delegate must be protected as well, maybe a simple locking dictionary is a better option.– taffer
1 hour ago
Yes, if the real-life scenario demands it, it can be polished. In that case the
ConcurrentDictionary<int, Table>.GetOrAdd method can be used instead of TryGetValue. Or, if the loader delegate must be protected as well, maybe a simple locking dictionary is a better option.– taffer
1 hour ago
add a comment |
A:
pros: none
cons:
it is not the responsibility of class to track its instances (see SRP)
non-thread-safe (see ConcurrentDictionary)
B:
pros:
- class is not burdened excess responsibilities that out its scope
cons:
- 'tracking'-code should be encapsulated to separate class that be responsible for creating instances, tracking them, managing time life strategy, etc (factory may fit for that)
- non-thread-safe
As mentioned above If you need to cache some items then use the MemoryCache.
add a comment |
A:
pros: none
cons:
it is not the responsibility of class to track its instances (see SRP)
non-thread-safe (see ConcurrentDictionary)
B:
pros:
- class is not burdened excess responsibilities that out its scope
cons:
- 'tracking'-code should be encapsulated to separate class that be responsible for creating instances, tracking them, managing time life strategy, etc (factory may fit for that)
- non-thread-safe
As mentioned above If you need to cache some items then use the MemoryCache.
add a comment |
A:
pros: none
cons:
it is not the responsibility of class to track its instances (see SRP)
non-thread-safe (see ConcurrentDictionary)
B:
pros:
- class is not burdened excess responsibilities that out its scope
cons:
- 'tracking'-code should be encapsulated to separate class that be responsible for creating instances, tracking them, managing time life strategy, etc (factory may fit for that)
- non-thread-safe
As mentioned above If you need to cache some items then use the MemoryCache.
A:
pros: none
cons:
it is not the responsibility of class to track its instances (see SRP)
non-thread-safe (see ConcurrentDictionary)
B:
pros:
- class is not burdened excess responsibilities that out its scope
cons:
- 'tracking'-code should be encapsulated to separate class that be responsible for creating instances, tracking them, managing time life strategy, etc (factory may fit for that)
- non-thread-safe
As mentioned above If you need to cache some items then use the MemoryCache.
edited 57 mins ago
answered 1 hour ago
vladimirvladimir
2,2741724
2,2741724
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55898506%2flist-or-dictionary-of-objects-inside-class%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Side note: do not expose fields but readonly properties: what if I assign
nulltoTables? E.g.Table.Tables = null;– Dmitry Bychenko
1 hour ago
@DmitryBychenko readonly is not good enough for this because you can still call any method from the Dictionary. The proper way to do this is to make it private and only interact with it using class methods.
– Chris Rollins
1 hour ago
1
@Chris Rollins: sure; at least expose
TablesasIReadOnlyDictionary<int, Table>readonly property.– Dmitry Bychenko
1 hour ago
@DmitryBychenko that's a clever approach
– Chris Rollins
1 hour ago
1
Have you considered using
MemoryCacheinstead?– mjwills
1 hour ago