|
PIEBALDconsult wrote: usually static classes are used for that (in C#),
Are you sure? The method I've come across is having a "normal" class but with a private constructor. There's then a single static reference to an instance of that class. Such as this article[^].
Does that make it any easier? I don't see anyway of making a class non-instatiable though, you might be able to do it with some mad reflection & stack calls but my concern is, is it worth the effort?
If there are only a few developers on it, just add some documentation and say the behaviour is undefined. If there are more (e.g. part of a library) then just document it.
I doubt it. If it isn't intuitive then we need to fix it. - Chris Maunder
|
|
|
|
|
Ed.Poore wrote: Are you sure?
With .net 2 and later, yes, but it also depends on how lazy you want the singleton to be, I usually don't need much laziness.
Ed.Poore wrote: with a private constructor
But in order to derive, the constructor must be at least protected because the derived class needs access to it (at least in the current framework). That would allow the derived class to be a non-singleton, which I don't want to allow.
Ed.Poore wrote: part of a library
Right, and I'm likely going to write an article on the class.
|
|
|
|
|
Just a thought: is this possible in C++? If it's not then I'm guessing it's going to be "impossible" to do in C#. Would you be able to provide more details as to the implementation surrounding this, i.e. how you intend to use it, so I can get a better idea of what you're trying to accomplish? I still think there's probably a better design method but can't be sure until I know more.
I doubt it. If it isn't intuitive then we need to fix it. - Chris Maunder
|
|
|
|
|
Ed.Poore wrote: is this possible in C++?
As if I'd know. I only dabbled in C++, I've spent most of my career (so far) in C, I only started doing C# because the only OpenVMS jobs I saw used COBOL.
Ed.Poore wrote: more details
Yeah, I'll work up a little example of what I have so far.
|
|
|
|
|
PIEBALDconsult wrote: Yeah, I'll work up a little example of what I have so far.
Yeah that'll help quite a bit.
PIEBALDconsult wrote: As if I'd know.
Well I'd probably know less, again only dabbling. Mainly C# but a bit of VB6 and quite a lot of C depending on the projects.
I doubt it. If it isn't intuitive then we need to fix it. - Chris Maunder
|
|
|
|
|
I can't think of any simpler examples so I'll just describe what I'm doing.
I'm writing a generic pool. Each item in the pool gets wrapped and added to a HashSet. The class is therefore a factory of these items as well. So, because it's a factory and there shouldn't be more than one pool of a given type in the appdomain, making the class a singleton seems appropriate.
public class GenericPool<T>
where T : class , new()
{
private sealed class GenericPoolItem : IGenericPoolItem<T>
{
private T item = new T() ;
}
private static readonly System.Collections.Generic.HashSet<GenericPoolItem> items =
new System.Collections.Generic.HashSet<GenericPoolItem>() ;
private static readonly System.Collections.Generic.List<GenericPoolItem> freelist =
new System.Collections.Generic.List<GenericPoolItem>() ;
public static IGenericPoolItem<T>
Reserve
{
get
{
GenericPoolItem result = null ;
lock ( items )
{
if ( freelist.Count == 0 )
{
result = new GenericPoolItem() ;
items.Add ( result ) ;
}
else
{
result = freelist [ 0 ] ;
freelist.RemoveAt ( 0 ) ;
}
}
result.Reserve() ;
return ( result ) ;
}
}
}
There is also an interface to expose only two members of the wrapper; Value and Free.
To use the class(es), one need only call Reserve, use the wrapped item, and then Free the wrapped item.
IGenericPoolItem<Widget> item = GenericPool<Widget>.Reserve ;
item.Free() ;
(I'll likely rename Reserve or change it to a method; it looks wrong as it is.)
For that I could use a static class, but as mentioned, I want to be able to derive.
Why? Well, one of the particular types I want to pool is StringBuilder (I still have yet to determine whether or not there's any performance benefit of that).
In the above snippet, Widget could be StringBuilder and it will work just fine except I would need to clear the StringBuilder each time I Reserve it. If I derive, I can override (kinda sorta) Reserve to perform the clearing.
public class StringBuilderPool : PIEBALD.Types.GenericPool<System.Text.StringBuilder>
{
public new static PIEBALD.Types.IGenericPoolItem<System.Text.StringBuilder>
Reserve
{
get
{
PIEBALD.Types.IGenericPoolItem<System.Text.StringBuilder> result =
PIEBALD.Types.GenericPool<System.Text.StringBuilder>.Reserve ;
result.Value.Length = 0 ;
return ( result ) ;
}
}
}
The classes work as I want. But in order to derive, the base class can't have a private constructor (which is usual for a singleton), the deriving class needs access to the base class' constructor, so I make it protected. But a deriving class could make its constructor public, undoing my efforts.
My solution is to have the constructor throw an exception:
protected GenericPool
(
)
{
throw ( new System.InvalidOperationException
( "Instantiating GenericPool is forbidden." ) ) ;
}
but I would prefer a compile-time error or something less heavy-handed.
I could, of course, just let people instantiate it, but the instances would be fairly useless without instance members... always remembering that probably no one else will use this anyway.
|
|
|
|
|
PIEBALDconsult wrote: always remembering that probably no one else will use this anyway.
In that instance I think you're probably overcomplicating things
How about moving the Reserve method to the GenericPoolItem , or rather provide the common stuff inside the container class and then provide the option to perform additional operations. For example if you do something like the following:
public static IGenericPoolItem<T> Reserve<T>()
{
if (T is ICustomReserve)
{
((ICustomReserve)default(T)).Reserve();
}
} Thus if you want to provide additional reserving you create a "wrapper" item and provide the implementation from there. Note the code would probably need rethinking but perhaps it provides some food for thought?
I doubt it. If it isn't intuitive then we need to fix it. - Chris Maunder
|
|
|
|
|
Ed.Poore wrote: probably overcomplicating things
Probably, but I try to encapsulate the overcomplications.
The Item does have a Reserve, but it only sets its reserved boolean. An earlier implementation allowed deriving the item wrapper, which allowed overriding the item wrapper's Reserve method, but I decided I prefer to keep the item wrapper private.
I also considered the ability to provide delegates to add functionality, something like after-new and after-reserve, but I haven't sold myself on the idea yet.
|
|
|
|
|
PIEBALDconsult wrote: Probably, but I try to encapsulate the overcomplications.
I suffer from the same problems, over-complicating things. After reading Mark Pilgrim's book "Dive into Python" and the section on unit testing I've got to say that I like his approach, write the minimal code to pass the first test and then add a bit more passing each test.
Unfortunately the work which I do doesn't lend itself to "easy" unit testing, from what I've read it requires all kinds of mock objects etc and I just haven't learnt any of that stuff yet. I'm only now using Subversion consistently across all projects
I doubt it. If it isn't intuitive then we need to fix it. - Chris Maunder
|
|
|
|
|
Ed.Poore wrote: only now using Subversion
Then you're ahead of me. I was going to install it, I read most of the manual, but then my colleague installed it so I lost interest. Part of the problem is that on a previous job we used CMS (the OpenVMS layered product) and I don't want to lower my standards.
|
|
|
|
|
Well I've got to say it's fantastic so far, I've bought a license for VisualSVN[^] and installed their "server" onto both my laptop and server and just use those. Having everything built into VS2008 is great.
norm.net and I are working on a joint project and using Assembla[^] as a repository. He's spent most of the time setting up workflows etc and really likes it, I haven't tried it yet. He's also installed AnkhSVN as opposed to VisualSVN (free opposed to £30) and he likes it, I only tried it a few years ago and it was more or less dead so hadn't expected it to have moved on but apparently it's working well. Personally I prefer VisualSVN because it uses Tortoise rather than rewriting it all, but then again I haven't tried Ankh so can't comment.
I doubt it. If it isn't intuitive then we need to fix it. - Chris Maunder
|
|
|
|
|
Although aimed at C++ this article[^] mentions something about deriving classes, haven't read through the article but might be worth a shot, the author appears to know what he's talking about.
I doubt it. If it isn't intuitive then we need to fix it. - Chris Maunder
|
|
|
|
|
I think the advent of static classes in .net widens the definition of Singleton somewhat.
A static class actually has zero instances, but otherwise fulfills the role.
So maybe the definition of Singleton needs to be broadened to "no more than one instance".
At any rate, I decided to simply make the class static and have events (OnNew, OnReserve, and OnFree) so the user can add special handling as desired.
PIEBALD.Types.GenericPool<System.Text.StringBuilder>.OnReserve +=
delegate
(
System.Text.StringBuilder Subject
)
{
Subject.Length = 0 ;
return ;
} ;
|
|
|
|
|
That probably makes more sense.
I doubt it. If it isn't intuitive then we need to fix it. - Chris Maunder
|
|
|
|
|
make it abstract
|
|
|
|
|
But I still want to keep derived classes from being instantiateable as well.
|
|
|
|
|
Yeach, I need that too. Unfortunately it seems that there is no way to
1.) Override static methods/properties
2.) Inherit from static classes
3.) Force particular static members by interface
Greetings - Gajatko
Portable.NET is part of DotGNU, a project to build a complete Free Software replacement for .NET - a system that truly belongs to the developers.
|
|
|
|
|
gajatko wrote: 1.) Override static methods/properties
Override , no, but you can make a new implementation.
gajatko wrote: 2.) Inherit from static classes
gajatko wrote: 3.) Force particular static members by interface
Which is why I can't use a static class for this.
|
|
|
|
|
public abstract class MyClassNname
At that point, it MUST be derived from in order to use it.
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|
|
Yes, but that's not entirely what I want. I want a derivable singleton. The base class is a singleton*, and any derived classes must also be singletons.
* Using a loose definition of "singleton", that considers a class with only static members as the zeroth instance.
modified on Monday, June 16, 2008 4:06 PM
|
|
|
|
|
Hi All,
I have a routine i'm working on that parses a file looking for chunk information. There are various possible chunks and some chunk types (that I have defined as structs) can sometimes occur more than once in any given file.
What is the best solution for having a single collection that can hold all/any of these created structs? Can I define a generic collection like:
List<Object> _wavinfo = new List<Object>();
I've not worked like this before, would be good to know if this is a sound idea or if there is a better method. Would it be better to have a strict definition of the object I know will only be created once and List<T> for the object I know might occur more than once?
I'm basically trying to keep the memory footprint as low as possible.
Cheers,
Jammer
Going where everyone here has gone before!
My Blog
|
|
|
|
|
List<object> works fine for that.
But using classes (rather than structs) with a common base class may be somewhat better.
Jammer wrote: I'm basically trying to keep the memory footprint as low as possible.
You probably needn't worry about that.
|
|
|
|
|
Hi,
Gotca, thanks for that, I started progressing with a List<object> . The problem is the similarity between these chunks is limited to just the ID of each chunk, after that they are all completely different in structure making a base class tiny. Or am I missing the point?
Jammer
Going where everyone here has gone before!
My Blog
|
|
|
|
|
Then stick with the List<object> unless you think someone may put something else in the List.
It kinda depends on what you need to do with the things.
|
|
|
|
|
How do I change the text of a window? I read the article regarding Window Tabifier and tried using the code. However, this produced read-only results.
Thanks in advance.
|
|
|
|