Reputation: 99694
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?
Upvotes: 15
Views: 8194
Reputation: 454
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
);
}
Upvotes: 0
Reputation: 564383
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.
Upvotes: 10
Reputation: 421978
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
Upvotes: 5