2

Lets say I have a class:

    class MyClass
    {
        object AnObject;

        public object GetObject(BlackBoxObjectMaker ObjMaker)
        {
            if(AnObject == null)
                AnObject = ObjMaker.MakeObject(); //MakeObject may call GetObject on this MyClass instance 

            return AnObject;
        }
    }

Whose job it is to create and provide access to objects using BlackBoxObjectMaker 'on demand' via GetObject().

Lets also say that, MyClass may be called upon to provide an object, 'x', the members of which contain members that reference 'x'.

In this case, GetObject() would end up calling itself on the same instance of MyClass, causing a stack overflow.

MyClass could be modified to detect when GetObject() is calling itself on the same instance, but in that case, how can GetObject() return a reference to AnObject that BlackBoxObjectMaker has not finished yet?

How can I provide a reference to an object, before I have a reference to that object? Is there such thing as a 'placeholder' in C#?

A likely duplicate, but apart from Will A's comment I cannot see anything as relevant to the context in this question

Extra information:

This is part of serialisation tool which is intended to support circular references. In this particular case the tool may be re-written so that a reference to an object may be taken before its properties are populated (and the reference is needed), as Henk Holterman says; but I would like an answer to this question, say for the time when BlackBoxObjectMaker really is is a black box.
This would be trivial in C++, so I am curious as to what options are available in C#.

Community
  • 1
  • 1
sebf
  • 2,831
  • 5
  • 32
  • 50
  • How would it be trivial in C++ ? I have trouble seeing that. – H H Mar 04 '12 at 14:51
  • @Henk OK, maybe trivial is too strong a word, but in C++ AnObject would be a pointer which I could return before initialisation is complete, and when ObjMaker has finished constructing the 'real' instance of AnObject I would copy it to the memory pointed at by the original AnObject pointer which I handed out. (I am aware this makes assumptions not detailed in the post but I was asking about a C# feature and was trying to distil it to the simplest example case so hope it will be forgiven!) – sebf Mar 04 '12 at 15:01

3 Answers3

4

// MakeObject may call GetObject on this MyClass instance

That is your root problem. Instead of trying to make this work, fix the design of your solution here.

Lets also say that, MyClass may be called upon to provide an object, 'x', the members of which contain members that reference 'x'.

No problem, as long as those members are instantiated second.

In short, there seems to be no reason to use recursion here. If you think there is, try to make it (a lot) clearer.

Is there such thing as a 'placeholder' in C#?

Not really. You could make your own wrapper but it will be difficult to get and use it right. Something like (but not exactly) a WeakReference.

H H
  • 263,252
  • 30
  • 330
  • 514
  • Agreed. The problem is the design. If consumers can reference AnObject before it's set, then the consumers need to be prepared to handle when AnObject is null. – Bob Horn Mar 04 '12 at 14:43
  • @Henk and Bob, I have added more detail to the question - and I also agree that my 'real' problem will be solved by redesign, but I would still like to know if there is a feature of the language that I am not aware of - just because you know one way to do it is no excuse to stop learning ;) – sebf Mar 04 '12 at 14:48
  • @sebf You mention that this is part of a serialization tool. If at the time that tool needs this property, it isn't set, how will having a pointer to it help? Isn't it already too late? – Bob Horn Mar 04 '12 at 15:11
  • @Bob, The tool will need the property, only so far as to set a property of the 'currently de-serialising' object to it. I.e. In C++, you could have an object with a member that is a pointer to something else - you can set this member without knowing what that thing is going to be so long as you know _where_ it is going to be (or, at least where you can move it...) – sebf Mar 04 '12 at 15:23
  • @sebf There is no "where" in managed code. Objects can be moved around in the memory on a whim of the garbage collector (aside from [pinned](http://msdn.microsoft.com/en-us/library/f58wzh21(v=vs.100).aspx) objects). – Branko Dimitrijevic Mar 04 '12 at 16:03
0

In addition to what Henk Holterman said, you may want to consider using Lazy.

Community
  • 1
  • 1
Branko Dimitrijevic
  • 50,809
  • 10
  • 93
  • 167
-1

Why dont you provide a static Method MakeObject() in the class BlackBoxObjectMaker?