Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why passing ref struct to methods actually passes a copy of a ref struct?

When I’m trying to pass a ref struct that looks like, say

public ref struct BufferWriter
{
    readonly Buffer* _pb;
    public int WrittenBytes;
    //...
    public bool Append(ReadOnlySpan<byte> buffer)
    {
        //...
        WrittenBytes += buffer.Length;
        //...
    }
    
}

to a method (Write100U8Chars(BufferWriter, Object) in the following example), a struct is not actually passed by a reference, but by the value:

protected override bool Serialize(object obj)
{
    //...
    fixed (Buffer* pb = &doc_body)
    {
        using (BufferWriter writer = new BufferWriter(pb))
        {
            writer.Append("UTF8 str"U8);
            // pb->Bytes is now 8
            // writer.WrittenBytes is now also 8
            Write100U8Chars(writer, obj);
            // pb->Bytes is now 108
            // But writer.WrittenBytes is still 8!
        }
    }
    //...
}

// A method that always calls BufferWriter.Append passing 100 UTF-8 chars (aka bytes) 
protected abstract bool Write100U8Chars(BufferWriter writer, object obj);

Because of the using block being kind of read-only context which, as I supposed, enforces making "defensive copies", I’ve attempted to remove the using block/directive:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

fixed (Buffer* pb = &doc_body)
{
    BufferWriter writer = new BufferWriter(pb)
    writer.Append("UTF8 str"U8);
    // writer.WrittenBytes is now 8
    Write100U8Chars(writer, obj);
    // No use of removing using: writer.WrittenBytes is still 8
}

Making BufferWriter a ref readonly struct makes no difference.

Passing a writer local to a method Write100U8Chars(BufferWriter, Object) with in parameter still makes no difference.

How can I make a ref struct be passed into abstract method by reference and not by value like it is the case with ordinary non-ref structs?

>Solution :

protected abstract bool Write100U8Chars(BufferWriter writer, object obj);

This call is passing writer by value. If you want to pass it by reference, it should be:

protected abstract bool Write100U8Chars(ref BufferWriter writer, object obj);

As far as I understand it, the ref in the struct declaration is used to define how the value type can be allocated (only stack) but it will still behave as a regular struct and get passed by value by default.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading