Writing to "this", or a general OOP question I guess...

D

Daniel Ervi

Hi All,

I have a question for the group as I can't seem to come up with any
suitable solutions. I'm not that new to programming or C#, but
neither am I very fluent yet, so I'd appreciate any help at mastering
my craft.

What I am trying to do is best illustrated in code:

public class TBase
{
public static HashTable itemCache = new Hashtable();
}

public class TItem : TBase
{
private string name;
private TItem()
{
// Disable default constructor
}
public TItem(string ItemKey)
{
// Check cache first
if (itemCache.ContainsKey(ItemKey))
{
// I know this isn't possible!
this = (TItem)itemCache[ItemKey];
}
// Not in cache so retrieve it from external source
else
{
this.name = "whatever"
// ... do expensive data loading routine
itemCache.Add(this.name, this);
}
}
}

TItem myItem = new TItem("ABC"); // Loaded from external
source
TItem myCachedItem = new TItem("ABC"); // Should be loaded from
cache

I know what I am asking for is a variation of a Factory pattern, but I
would like to keep the standard C# syntax. A factory pattern would
disable the default constructor and then use a custom static
constructor to return the object from the cache. I can do this, but
it deviates from the standard C# syntax. Ideally I'd like to overload
the new operator, but C# can't do this.

I guess my question can be summarized as what is the best way to
replace the "this" reference with an already constructed Item,
retrieved from the cache, while still using new?

Thanks for any advice!

Daniel
 
R

RCS

You are so close, you don't even know!! Should I give it away???

You want the Singleton Pattern - does exactly what are you looking for. It
will only create an instance of your class the first time, then every other
call to New will re-use the original instance of the class. Right??

I don't have any good examples handy, do a search, lots of examples on the
web. Post back if you can't find any good ones. Good luck!
 
B

Bruce Wood

I have two answers to your question.

First, there isn't any way to do what you want to do. By the time the
constructor is called (in C#, C++, VB.NET, ... ) memory for the object
has already been allocated in a different place than the memory that
the object in the hash occupies, so there is no way to "return" the
object that you've stored away. The constructor's job is just to fill
in the already allocated memory; it can't change the location (and thus
the reference identity) of the object.

That said, the key statement you made is wrong... or at least off base.
Using a static method to return the object instance does not "deviate
from the standard C# syntax" _for a factory pattern_. Even if you could
find some way to get the effect you want, your factory would be
different from every other factory out there written in C#, and so
would be difficult to maintain.

Yes, in C++ you can override "new" and create an "invisible object
factory," but in C# the standard syntax is to use a static method. It's
what most of us are doing and what anyone coming along after you
looking at your code will recognize.
 
T

Till Meyer

RCS said:
You want the Singleton Pattern - does exactly what are you looking for. It
will only create an instance of your class the first time, then every other
call to New will re-use the original instance of the class. Right??

He doesn't need the Sigleton Pattern, but the Builder Pattern.

Till
 
S

sadhu

While your argument about using a static method for the factory pattern
is true, it is indeed possible to assign to this if that particular
type is a struct (value type). If you look at the ECMA standard, it
says that for structs, "this" is a variable, not a value and hence can
be assigned to (like an out/ref parameter).

Regards
Senthil
 
A

ace

RCS:

Thanks for the advice on the Singleton Pattern. I'm not sure it is the
right match for me though as I need multiple instances (ie: "ABC",
"BCD", etc) of the TItem class. It may apply here though, and I'll
have to think about it a little more.

Bruce:

I didn't mean to imply that the Factory Pattern syntax deviated from
the C# standard, but in hindsight I see that's how I described it.

A little more detail may help. I'm working on a class framework which
has a large number of classes available to the programmer. My goal in
the TItem example was to convey that I want to have multiple instances,
but none with a duplicate ItemKey. For effeciency I want to have a
global cache operating beneath all the objects to apply transparent
caching to the end users of the framework. I'd like to retain the
"new" syntax simply because it is consistent with the rest of the
objects in the framework, and it might be akward for me to have only
one or two classes using the different factory-style syntax.

I feel that I'm close to a solution, but I just can't seem to work it
out in my head yet, hence my post looking for a fresh perspective. In
any case, thanks for taking the time to offer your thoughts!

Till:

I have to admit that I am a complete design patterns newbie, having
acquired two books on them less than a week ago! I haven't covered the
Builder Pattern yet, but will brush up on it and see if it will help.
Thanks for the tip!

Daniel
 
B

Bruce Wood

True, but structs are copied in many situations: when they're assigned,
when they're passed as arguments, etc, so the OP's goal of having "only
one of each type" in memory at any one time (where "type" is determined
by some key) cannot be achieved using structs.
 
B

Bruce Wood

Hmmm. I see your problem, but I see no way around it.

The "new" operator allocates memory for the object instance and then
passes control to your constructor. I see no way to intervene in that
process (as you can in C++) in order to have the result of "new" be
anything other than the memory allocated by that "new" operation by the
runtime.

As well, the .NET Framework itself uses static methods to return "new"
objects here and there (in precisely this sort of situation), so if you
did have a few classes that instantiated themselves this way it would
not be an unfamiliar paradigm for your users.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top