views:

91

answers:

2

I'm trying to make an AtomicReference class in C# and I want to keep the field reference protected, but I also need to return the value in the get method:

class AtomicReference
{
    private Object _value;

    public AtomicReference()
    {
        _value = new Object();
    }

    public AtomicReference(Object value)
    {
        OptimisticSet(value);
    }

    public Object CompareAndSet(Object newValue)
    {
        return Interlocked.Exchange(ref _value, newValue);
    }

    public void OptimisticSet(Object newValue)
    {
        do { 
        } while (_value == Interlocked.CompareExchange(ref _value, _value, newValue));
    }

    public Object Get()
    {
        // Don't leak the field reference
        const Object constVal = _value;
        return constVal;
    }
}

It's a bit of a clumsy way around the problem... I can't make the field readonly, because I need to be able to set it. Is there a better solution than mine?

UPDATE: Thanks for the quick responses! It was rightfully pointed out that the reference will be protected if I simply return _value. I also want to protect the _value from mutating. If I allow the _value to mutate outside of the AtomicReference, then it defeats the entire purpose of making this class... is there a way to achieve that?

+2  A: 

Even if you try, it is not possible to return a reference to a field in C# (without unsafe code) or Java. (I don't mean a reference to an object)

You can simply write return _value; your callers will not be able to write to the field.

SLaks
True that callers cannot change _value itself to refer to a different object, but won't callers be able to mutate the object that _value refers to? For example, if object is really of type Square, callers will be able to do `obj.Side++`. My understanding of the question is that he wishes to avoid such mutations.
gWiz
If so, he's out of luck; that's not possible to do. (Unless you restrict to value types or `IClonable`) From the fact that he accepted the answer, I _assume_ that he isn't.
SLaks
Yeah I re-read the sample and it looks like he only cares about the references.
gWiz
Why did you unaccept the answer?
SLaks
Not possible to do? Do I have to clone the object? A constant won't do it? What's the solution?
Lirik
@Link: What exactly are you trying to do? If you don't want people to make the `_value` field point to a different object (like Java's `AtomicReference`), you're fine. If you don't want the object that `_value` points to to change at all, it's not possible.
SLaks
@SLaksOK... I understand now. For some reason I was thinking that if I pass an integer I will be able to protect it. That is a completely different concept that is solved by the AtomicInteger class. Sorry for giving you the run-around! I really appreciate your help! :)
Lirik
+1  A: 

C# does not support C++'s const keyword, which allows for immutable references to mutable objects.

There are only two ways to do what you're asking.

  • You could clone the object whenever you return it. Note that this will only work for clonable objects, and it'll be quite slow.
  • You could only support value types.
SLaks
Thanks! I'm sorry, I was inadvertently thinking of two separate ideas... I was thinking of passing an Int32/Int64 to the AtomicReference class, completely blanking out that the proper way to do it is with an AtomicInteger.
Lirik