Jump to content
  • Advertisement
Sign in to follow this  
bakery2k1

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

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by Ra
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.


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

Quote:
Original post by kanato
You 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 this post


Link to post
Share on other sites
Quote:
Original post by bakery2k1
Unfortunately 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 this post


Link to post
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 this post


Link to post
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 this post


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

:)


Of course! [rolleyes]

Quote:
Original post by paulecoyote
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.


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 this post


Link to post
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!