[.net] Reference to a value type in C#

This topic is 4101 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Is it possible in C# to get a reference to an object of a value type? Consider the code:
struct S
{...}

S s1[] = new S[10];
S s2[] = new S[10];

...

int i = ... //0 <= i < 20

S s = (i < 10) ? s1 : s2[i - 10];
//Do something with s


Suppose "do something with s" involves modifying s. Since s is a copy of the array element, any modifications will be made to the copy. What can I do if I want to actually alter the array element itself? In C++, this would be a simple matter of making s a reference ("S & s"); is there a similar construct in C#?

Share on other sites
Nope. You could do all kinds of hacks with pinning and taking the address of the array element, but if you really want to do that you should be using a reference type.

In your case you could just get away with storing the new index and then operating directly on that element, or modifying s and then copying it back into the array.

Share on other sites
You could pass it as a reference to a function:

void SomeFunction(){    Point [] points = new Point[10];    DoSomething(ref points[4]);}void DoSomething(ref Point p){    p.X = 4;}

This works for arrays and variables but does not work with properties or indexers in generic containers, like List<Point>.

Share on other sites
Quote:
 Original post by RaIn your case you could just get away with storing the new index and then operating directly on that element, or modifying s and then copying it back into the array.

Thanks. It looks like modifying and then copying back is the best solution in this situation.

Quote:
 Original post by kanatoYou could pass it as a reference to a function:DoSomething(ref points[4]);

Unfortunately this won't work here:
ref ((i < 10) ? s1 : s2[i - 10])
causes an error about "ref" requiring an assignable object.

Share on other sites
Quote:
 Original post by bakery2k1Unfortunately this won't work here:ref ((i < 10) ? s1 : s2[i - 10])causes an error about "ref" requiring an assignable object.

if (i < 10) DoSomething(ref s1);
else DoSomething(ref s2[i-10])

:)

Share on other sites
It's very possible! And very easy, but it usually involes unsafe code, which is perfectly fine but should be used with care as it's not really CLR best practice.

inside a unsafe { } code block you are allowed to use the address of operator & to get a pointer of any value type. You can do this for any .NET type (classes as well) but it can quickly get error prone.

As long as your struct S is a non-managed type you can do this.

S s = new S(); // initialize
S* p = &s;

This is very similar to the ref keyword for passing something as a reference, but it's more powerful. Since it's not a managed pointer.

If you have an array you can use a fixed statment inside a unsafe code block to lock memory down to really do something cool.

fixed( S* p1 = s1 )
{
fixed( S* p2 = s2 )
{
S* s = i < 10 ? p1 + i : p2 + i - 10;
// do something with 's'
}
}

It's like pointers in C, and it's generally bad CLR practice but it will do the trick, and if you need this, this is what you need to do.

Side note: Since C# is managed, memory is collected automatically, but it's also moved around. The fixed statment prevents the CLR from moving memory, and it's a bad thing if you do GC collect with fixed memory. A simple way to avoid it is to just fix memory wherever needed, and only for the duration of the procedure. It's could impose a preformance problem, but as with all things, profile it!

There is a struct called GCHandle which can be used for really advanced stuff and with managed reference types, look it up on MSDN if you want to use it.

Share on other sites
I am trying to figure out why you are trying to get a value type act like a reference type?

If your type is mutable, you should probably use a class.

Share on other sites
Replace the word "struct" with "class". FIXED!

Share on other sites
Quote:
 Original post by Niksan2if (i < 10) DoSomething(ref s1);else DoSomething(ref s2[i-10]):)

Of course! [rolleyes]

Quote:
 Original post by paulecoyoteI am trying to figure out why you are trying to get a value type act like a reference type?If your type is mutable, you should probably use a class.

When to use a struct and when to use a class is something I'm still trying to figure out. Thinking about it, "mutable => class" seems to be a good guideline.

Is there any similar advice that would make my life easier?

Share on other sites
Most of the time you will want to use reference types. Value types should be used for what their name implies: objects that act as a value, such as integers, Matrices, vectors, floats, points, coordinates, etc.

1. 1
2. 2
Rutin
19
3. 3
khawk
18
4. 4
5. 5

• 9
• 12
• 16
• 26
• 10
• Forum Statistics

• Total Topics
633769
• Total Posts
3013758
×