Theodor Zoulias
Theodor Zoulias

Reputation: 43996

How to box and unbox a struct with type safety

There is a struct in the .NET platform that I would like to use as state for my class. It is important that the struct is built-in, so I can't change it. Lets say that this built-in struct is the ImmutableStruct below.

struct ImmutableStruct
{
    public string Value { get; }

    public ImmutableStruct(string value) { Value = value; }
}

My class is required to be thread-safe, so the state must be declared volatile. Of course there are other ways to achieve thread-safety, but lets say that a volatile field has been chosen as the best option for the specific case. So I code my class like this:

class MyClass
{
    private volatile ImmutableStruct _state = new ImmutableStruct("SomeString");
    // Error CS0677
    // 'MyClass._state': a volatile field cannot be of the type 'ImmutableStruct'

    public ImmutableStruct State => _state;

    /* Method that mutates the _state is omitted */
}

Unfortunately the compiler does not allow a volatile struct field. So I decide to use boxing and unboxing:

class MyClass
{
    private volatile object _state = new ImmutableStruct("SomeString");

    public ImmutableStruct State => (ImmutableStruct)_state;

    /* Method that mutates the _state reference is omitted */
}

This works, but casting from objects causes me anxiety, because the program becomes exposed to possible run-time errors. I would like a type-safe solution, with the compiler ensuring the correctness of the program at compile-time. So my question is: Is there any way to box and unbox a struct with type safety?

Btw there is a related question about marking structs as volatile: Volatile for structs and collections of structs. My question defers in that it focuses specifically to the type-safety of the boxing/unboxing operation.

Upvotes: 1

Views: 292

Answers (2)

Yirkha
Yirkha

Reputation: 13868

There is also a class StrongBox<T>, doing essentially the same as described in Guru's answer, but available out of the box since ever (.NET Framework 3.5).

See also:

Upvotes: 1

Guru Stron
Guru Stron

Reputation: 143513

How about creating generic wrapper like this:

public  class ReadonlyStructWrapper<T> where T: struct 
    {
        public T Value { get; }
        public ReadonlyStructWrapper(T value)
        {
            Value = value;
        }
    }

Upvotes: 2

Related Questions