Singleton Pattern and Collections

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

At the beginning of my C# days (about 6 months ago) I learned about the
Singleton pattern and implemented for Reference data, such as the kind that
appears in an Options dialog box. My Singleton code looks like this:

public sealed class Reference
{
private static readonly Reference instance = new Reference();

// Make the default constructor private, so that nothing can directly
create it.
private Reference()
{
}

// public property that can only get the single instance of this class
public static Reference Data
{
get
{
return instance;
}
}


And then after that, but within the class, I add whatever properties I want.
This has served me very well.

But now I'd like to expand the use of the Singleton pattern to include
collections such as Users. My Users collection will be populated with a User
object, that itself will contain many properties such as "ID", "Name", etc.

I hit a roadblock though when I copied the above code to a new class I had
built for this purpose. The problem - I think - is that because the parent
class is sealed I can no longer access sub-classes like "User".

So I'm not sure how to proceed, other than removing the Singleton pattern.
This works but isn't really correct because now a developer could incorrectly
instantiate multiple versions when there really should be only one.

Any ideas how I could resolve this?
 
Robert W. said:
At the beginning of my C# days (about 6 months ago) I learned about the
Singleton pattern and implemented for Reference data, such as the kind that
appears in an Options dialog box. My Singleton code looks like this:

<snip>

That all seems to be correct.
And then after that, but within the class, I add whatever properties I want.
This has served me very well.

But now I'd like to expand the use of the Singleton pattern to include
collections such as Users. My Users collection will be populated with a User
object, that itself will contain many properties such as "ID", "Name", etc.

I hit a roadblock though when I copied the above code to a new class I had
built for this purpose. The problem - I think - is that because the parent
class is sealed I can no longer access sub-classes like "User".

So I'm not sure how to proceed, other than removing the Singleton pattern.
This works but isn't really correct because now a developer could incorrectly
instantiate multiple versions when there really should be only one.

Any ideas how I could resolve this?

I don't think I quite understand you. Are you saying there should only
be one collection of users? If so, create some class representing the
users, and make that a singleton. I don't see where class derivation
comes in...

You don't derive from a singleton class to create another singleton
class - singleton classes should always be sealed (and/or only have a
private constructor) as otherwise you end up with something which isn't
definitely a singleton.
 
I think I see Robert's problem. Maybe.

Robert: you can't create a generic "singleton reference class" and then
inherit from it to get different kinds of singletons. I doesn't work
that way.

You have to implement the Singleton pattern separately for each class
that you want to be a Singleton. These classes _can_ inherit from a
common parent, if in real-world terms it makes sense to do so, but the
parent wouldn't be a Singleton... it would likely be abstract, or
designed so that only its child classes could instantiate it.

Was that what you were asking?
 
Jon, Bruce,

Thank you both for responding. All of your insight helped me. What I was
doing wrong was including nested classes - such as "Users", "User",
"Devices", and "Device" inside the parent class. Once I turned the parent
class into a sealed Singleton class then I could no longer access the nested
classes.

Seems so simple now but I was completely stumped earlier today.

My dilemma now is that for another complex class I had built a completely
generic XML export function (the built-in one never worked) and a fairly
generic XML import function. Unfortunately they don't appear to work when
the parent class is a Singleton one. But I'm going to investigate if a
little tweaking would resolve it.

If that doesn't work then I can just forego the Singleton-nature and only
instantiate the parent class once. True this wouldn't be correct for
circulating the library to others, but since I'm in control of it myself it
might suffice.

I think I'm at that point in my project now where while I want to do
everything perfectly and generically, I also have to get the damned thing
done! :-)
 
Robert W. said:
Thank you both for responding. All of your insight helped me. What I was
doing wrong was including nested classes - such as "Users", "User",
"Devices", and "Device" inside the parent class. Once I turned the parent
class into a sealed Singleton class then I could no longer access the nested
classes.

You should be able to. Note that nested classes aren't derived from the
containing class. There shouldn't be any problem there.

Personally I wouldn't recommend using nested classes terribly often -
they're good for classes which are *only* used by their containing
classes (so they can be basically invisible to everything else) but
other than that, I'd stick to "one class per file".
 
Robert said:
At the beginning of my C# days (about 6 months ago) I learned about the
Singleton pattern and implemented for Reference data, such as the kind that
appears in an Options dialog box. My Singleton code looks like this:

That's a Singleton alright: a global variable holding an instance of a
class with only one instantiation. (As you may suspect, I'm not really
convinced singleton is a good design-pattern :)
But now I'd like to expand the use of the Singleton pattern to include
collections such as Users. My Users collection will be populated with a User
object, that itself will contain many properties such as "ID", "Name", etc.

Do you even *need* a UserCollection class? can't you use an ISet<User>
implementation? (which unfortunatly isn't available in .NET1.1 but can
be simply implemented using an IDictionary):

void f(ISet<User> users) {
foreach ( User u in users )
...;
}

Lets assume UserCollection have som functionality not in ISet<User>,
then and lets implement it:

public class UserCollection:
// you may implement ISet by composition or inheritance,
ISet<User>
{
public Add(User u) { ...something not in ISet implementation... }
... more things not in ISet implementation
}

now, I would just pass the UserCollection to operate on amongst functions:

void f(UserCollection users, ...) {
foreach ( User in users )
...
}

Why do you need to guarantee that only one instance of a UserCollection
ever exists? What value does it add to your program? what value does it
remove? (remember, it makes UserCollection a global variable and
prevents others from using the collection to represent Users).

If you believe passing the UserCollection around is too bothersome, you
can add:

public static UserCollection Global = new UserCollection();

to class UserCollection. Now UserCollection.Global is effectively a
global variable (which is like a singleton, without guarantee that the
class is only intantiated once). This makes using code look like:

void f(...) {
foreach ( User in UserCollection.Global )
...
}

I have, (almost) never seen anywhere where the "only one instance of a
class" property yields value to a programs. the "global variable"
property is used often though... and people are even pround of it
because Singleton is a design pattern -- even though they haughtily
snorts at global variables as a rule!
 
Helge Jensen said:
That's a Singleton alright: a global variable holding an instance of a
class with only one instantiation. (As you may suspect, I'm not really
convinced singleton is a good design-pattern :)

What would you use instead ? If you wanted to be sure that there is only one
instance of a certain class ?
 
Jon Skeet said:
Personally I wouldn't recommend using nested classes terribly often -
they're good for classes which are *only* used by their containing
classes (so they can be basically invisible to everything else) but
other than that, I'd stick to "one class per file".

Or which are only exposed via an interface visible elsewhere;
enumerators, for example.
 
Helge (and others),

You raise some interesting points. Let me go back to basics [of what I'm
trying to accomplish]. I have some data that I call "SysInfo" - User Info,
Supported Device (my app works with PPC apps), and Global Options. I also
have some data that I call "RefData" - Countries, Cities, Area Codes and
other such things.

In both cases, I need this data to be available to every module. Yes, I
suppose I could just pass these data objects around but I think that'll get
quite cumbersome.

I originally implemented the Singleton pattern because I thought (and I
think I had read) that it was the right solution for this kind of data:
- Global to everything
- Instantiated only once

While it's true that if I'm the only developer then I can just instantiate a
regular (non-Singleton) object and know not to instantiate it again, I
thought that Singleton was better if multiple developers got involved to
ensure that everyone was forced not to have multiple copies of what should be
just one set of data.

I very much welcome back any and all further feedback to this.
 
Ollie Riches said:
Thanks for tht Jon, Shot down in flames again :)

Oh, I don't think that was very flamy. You should see me get going when
people claim that C# passes objects by references by default ;
 
Helge,

Can I ask you a quick follow-up to something you said?

Your Singleton alternative used this syntax:
public static UserCollection Global = new UserCollection();

But then that means that everytime I want to reference anything I have to
prefix it with "UserCollection.Global." This just seems so redundant to me.

Is there a way to instantiate a global variable so that I could just
reference the various properties with this prefix: "UserCollection." ?
 
Back
Top