views:

75

answers:

2

I am looking for a class that defines a holding structure for an object. The value for this object could be set at a later time than when this container is created. It is useful to pass such a structure in lambdas or in callback functions etc.

Say:

class HoldObject<T> {
 public T Value { get; set; }
 public bool IsValueSet();
 public void WaitUntilHasValue();
}

// and then we could use it like so ...

HoldObject<byte[]> downloadedBytes = new HoldObject<byte[]>();
DownloadBytes("http://www.stackoverflow.com", sender => downloadedBytes.Value = sender.GetBytes());

It is rather easy to define this structure, but I am trying to see if one is available in FCL. I also want this to be an efficient structure that has all needed features like thread safety, efficient waiting etc.

Any help is greatly appreciated.

+3  A: 

Never seen a class like that, but should be pretty simple.

public class ObjectHolder<T>
{
    private T value;
    private ManualResetEvent waitEvent = new ManualResetEvent(false);

    public T Value
    {
        get { return value; }
        set
        {
            this.value = value;

            ManualResetEvent evt = waitEvent;

            if(evt != null)
            {
                evt.Set();
                evt.Dispose();
                evt = null;
            }
        }
    }

    public bool IsValueSet
    {
        get { return waitEvent == null; }
    }

    public void WaitUntilHasValue()
    {
        ManualResetEvent evt = waitEvent;

        if(evt != null) evt.WaitOne();
    }
}
Adam Robinson
Thanks for the implementation. I have a very similar impl done already and wondered if it was a common use and hence the ask for a standard .NET class.
Charles Prakash Dasari
Why not use `Task<T>`? (see my answer)
Steven
@Steven: Because it doesn't meet the OP's requirements. There is no setter because Task represents the return value of a function, not a simple value container.
Adam Robinson
@Adam: I'm sorry Adam, but I'm not sure whether it doesn't meet his requirements. While his class definition has a setter for the value, his requirement is "The value for this object could be set at a later time than when this container is created.". Of course this is exactly what the `Task<T>` class will do when the delegate finishes; it sets that value (at a later time). Of course it is impossible to set this value multiple times, if that’s your point, I must agree. However, it's not clear to me whether this is actually needed.
Steven
@Steven: It seemed from the question that the OP wanted the ability to pass this container around to multiple functions, not simply obtain the return value of a single function.
Adam Robinson
I see, you're right about that. He also commented on my answer about that. You've got my +1.
Steven
+3  A: 

What you're trying to accomplish feels a lot like a future. Early CTP's of .NET 4.0 TPL had a Future<T> class. With the RTM of .NET 4.0 it has been renamed to Task<T>. If you squint, you can see the resemblance between:

class HoldObject<T>
{
    public T Value { get; set; }
    public bool IsValueSet();
    public void WaitUntilHasValue();
}

and

class Task<T>
{
    public T Value { get }
    public bool IsCompleted { get; }
    public void Wait();
}

If you're not using .NET 4.0 yet, you can download the Reactive Extensions for .NET 3.5sp1. It contains a System.Threading.dll assembly that contains TPL for .NET 3.5.


While the Value is read-only, changing it can of course be done by the return value of the delegate you supply the task. Of course I'm not exactly sure if this meets your requirements, but your example can be written as follows:

var downloadBytesTask = Task<byte[]>.Factory.StartNew(() => 
    DownloadBytes("http://www.stackoverflow.com"));

if (!downloadBytesTask.IsCompleted)
{
    downloadBytesTask.Wait();
}

var bytes = downloadBytesTask.Value;
Steven
This is a great answer, thanks for this. But my requirement is a little different from this. Looking closely, what I wanted is a container that can be passed around to a piece of code that might be executed at anytime, which btw, fill this value - usually used in a callback of an async operation. Whereas a Task is "that definition of the piece of code" which can return a value. Though they both can be used interchangeably in most cases, they aren't exactly the same. Also, Task itself defines a different programming model, that doesn't naturally fit into all my scenarios.
Charles Prakash Dasari