Shai Avr
Shai Avr

Reputation: 1350

How to extract a struct array element into a variable without copying in C#?

I have a little question about arrays of struct in C#: lets say I have a struct Foo:

struct Foo
{
    public string S;
    public int X;
    ...
    ...
}

and I have an array of Foo: Foo[] arr = ...

In one method, I use arr[i] quite often, so I'd like to keep it in a local variable (the expression for i is also a little long):
var f = arr[i]

Now, my problem is that I know structs are value type, which means assignments like this cause a copy. The struct is a little big (7 strings and a bool), so I'd prefer to avoid copying in this case.

If I am not mistaken, the only way to access the struct's fields without copying the struct is to use the array directly: arr[i].S or arr[i].X, but this quickly becomes annoying to read. I'd really like to keep the array element in a local variable, but I don't want to waste performance by copying it into the variable.

Is there a way to make something like a reference variable (similar to C++) to avoid copying? If not, than I'm curious if it's something the compiler optimizes?

How should I deal with this element? Can I put it in a local variable without copying or do I have to access it through the array to avoid copying?

Thanks in advance.

Upvotes: 2

Views: 1622

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1502486

You can do this in C# 7 and later using ref local variables:

using System;


public struct LargeStruct
{
    public string Text;
    public int Number;
}

class Test
{
    static void Main()
    {
        LargeStruct[] array = new LargeStruct[5];

        // elementRef isn't a copy of the array value -
        // it's really the variable in the array
        ref LargeStruct elementRef = ref array[2];
        elementRef.Text = "Hello";

        Console.WriteLine(array[2].Text); // Prints hello
    }
}

Of course, I'd normally recommend avoiding:

  • Large structs
  • Mutable structs
  • Public fields (although if it's mutable, doing that via public fields is probably best)

... but I acknowledge there are always exceptions.

Upvotes: 6

Related Questions