15

Does a method like this exist anywhere in the framework?

public static void Swap<T>(ref T left, ref T right) { T temp; temp = left; left = right; right = temp; } 

If not, any reason why?

3 Answers 3

10

There is Interlocked.Exchange. This does it in a thread-safe, atomic call.


Edit after comments:

Just to clarify how this works using Interlocked.Exchange, you would do:

left = Interlocked.Exchange(ref right, left); 

This will be the equivalent (in effect) to doing:

Swap(ref left, ref right); 

However, Interlocked.Exchange does this as an atomic operation, so it's threadsafe.

Sign up to request clarification or add additional context in comments.

5 Comments

Interlocked.Exchange sets a value, it doesn't actually swap values. You would still need to save a temp, and call Interlocked.Exchange twice, so you don't really gain anything.
Interlocked.Exchange is not really equivalent of the specified Swap. It only changes the first value and doesn't touch the second (itself).
@jrista: Why would you need to call it twice? Interlocked.Exchange returns the ~original~ value, so you only need to call it once, and use the returned value. See my edit.
@Reed: That's why I mentioned "itself," in my comment. As mentioned in the answer, it's also different due to atomic semantics that might have overhead...
It's misleading to say this is atomic, the assignment to left will happen after the assignment to right.
5

No, the framework does not have such a method. Probably the reason is there's not much benefit to have it built-in and you could very easily (as you did) add it yourself. This also requires use of ref as parameter, which will greatly limit the use cases. For instance, you couldn't do this:

List<int> test; // ... Swap(ref test[0], ref test[1]); // won't work, it's an indexer, not an array 

Comments

0

The reason is that C# does not have references to slots, so implementing such a method requires expression parameters, which is somewhat advanced stuff:

 static void Swap < Model, Value > ( Func < Model, Value > getter, Action < Model, Value > setter, Model m1, Model m2 ) { Value v = getter ( m1 ); setter ( m1, getter ( m2 ) ); setter ( m2, v ); } 

Of course, a quality implementation would check that things are unequal first. You can even do away with a separate setter:

 static void Swap < Model, Value > ( Expression < Func < Model, Value > > getter , Model m1, Model m2 ) { var valueParam = Expression .Parameter ( typeof ( Value ) ); Swap ( getter .Compile (), Expression .Lambda < Action < Model, Value > > ( Expression .Assign ( getter .Body, valueParam ), new [] { getter .Parameters [ 0X0 ], valueParam } ) .Compile (), m1, m2 ); } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.