Swap two variables without using a temporary variable
Asked Answered
B

30

125

I'd like to be able to swap two variables without the use of a temporary variable in C#. Can this be done?

decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);

// Swap each:
//   startAngle becomes: 355.87
//   stopAngle becomes: 159.9
Brushwork answered 29/4, 2009 at 23:9 Comment(4)
decimal stopAngle = Convert.ToDecimal(159.9); decimal startAngle = Convert.ToDecimal(355.87);Clough
Never convert a floating point to a decimal. It should be string, not a floating point, e.g. Convert.ToDecimal("159.9")Fry
Technically, no. You can only make your code appear as though it does, but underneath, there must always be a third variable: Here is why, All variables are a declarion of type: (Number of bit's the type can hold) and value (The actual value of said type) if you have a memory block, with something like a 4 bit type -> 1000 (1 in decimal) (Variable A) and another memory block with something like a 4 bit type -> 0100 (2 in decimal) (Variable B) When you want to store A in B, the value of b will be overwritten by A. There is no way for you to retain the value of B.Calla
The ONLY way to retain the value of B, in my previous text, is to store B, in some other value. (Temporary or not) until such a time that the previous Value of B (saved in the third variable memory block) has been stored in A. Then you can free up the third values memory for something else, and you are back to, two variables, but swapping values MUST be done this way. Then someone will say "What if it done by reference and not value?" It's the same problem, the reference to A and the reference to B, must be held, while one reference points to, two values, otherwise, you can't reconnect.Calla
O
139

First of all, swapping without a temporary variable in a language as C# is a very bad idea.

But for the sake of answer, you can use this code:

startAngle = startAngle + stopAngle;
stopAngle = startAngle - stopAngle;
startAngle = startAngle - stopAngle;

Problems can however occur with rounding off if the two numbers differ largely. This is due to the nature of floating point numbers.

If you want to hide the temporary variable, you can use a utility method:

public static class Foo {

    public static void Swap<T> (ref T lhs, ref T rhs) {
        T temp = lhs;
        lhs = rhs;
        rhs = temp;
    }
}
Olcott answered 29/4, 2009 at 23:20 Comment(9)
That's fine for integers or fixed-point numbers. With floating point numbers you'll end up with minute rounding errors. They may or may not be big enough to matter, depends on how you're using the numbers.Monocyte
As long as you don't run into overflow issues, that works just finePalaestra
@Kennet Belenky: indeed, but i don't see another work around, except a temporary value. So I think it's the only "good" way to solve this problem. (Sorry for my English, if I made mistakes)Olcott
@Janusz Lenar: Well in languages with pointer manipulation you could use the same trick to swap the pointers. In C# you can do this in an unsafe environment. :D But anyway I admit swapping objects,ect. without a third variable is a bad idea (in reaction to this. __curious_geek). But the question said explicitly to do it without an extra variable.Olcott
This technique is more computationally expensive than using a temporary variable.Sentimental
Yes I know, but again, the question asked if it was possible to do it without a temporary variable. If you compile the code with a temporary variable, it probably won't even require additional memory since the temporary variable would only be stored in a register of the processor. But I suppose the question was homework or something equivalent.Olcott
I don't like the sentence "swapping without a temp variable is a very bad idea". Many languages support swapping variables in a clear way without the mistake-prone 3-line shuffle, so it's logical to ask if C# does. Python: a, b = b, a, C++: std::swap(a, b).Morin
@KevinS: Sure, some CPU's even have specific instructions or a macro for it. But using mathematical tricks to process it is not how it is supposed to be done. It is error-prone, is hard to understand. And for Python, what you do is create a tuple as a third variable. For C++'s swap you simply hide the third value in the method (or it is processed by the CPU directly). In case it is however not available, not using such variable is asking for trouble.Olcott
I'm not sure why the negative comment from paxdiablo. This solution is a very Functional and compact solution. And the method says what it does. So what is the problem with it??? Correction: A more functional approach now with Tuples is to do an inline swap. THAT is "the functional way". (a, b) = (b, a);Lenticular
B
302

C# 7 introduced tuples which enables swapping two variables without a temporary one:

int a = 10;
int b = 2;
(a, b) = (b, a);

This assigns b to a and a to b.

Blayze answered 28/8, 2016 at 11:29 Comment(10)
It's just a shame this feature didn't exist previously, where he would've potentially learned a powerful new language construct that would've given him more tools in his toolbox to crack problems open with, instead of all the useless rants above.Kohlrabi
How performant is this though? I always fear some "Tuple" instance created on the heap internally and all those fancy things happening.Ditzel
@Ditzel reddit.com/r/ProgrammerTIL/comments/8ssiqb/…Capers
-1, I just tested this approach on IDEone and it does not work with primitive types, unlikely it'll work with reference type data either. ideone.com/03zt9UTrull
@Trull Your link show correct results. Why you say it does not work with primitive types?Nicotinism
No it doens't... It shoes a and b both equal to 10 after instead of a successful swap.Trull
@Trull that is because the site you are using is using the gcms compiler which targets mscorlib2.0 (.NET Framework 2.0, not .Net core) You need to use a more recent compilerBlayze
I did try this on my local PC too using .NET Framework 4.7 and it didn't work. Also the question has no tags or mention of specifically targetting .NET Core. Either way, it's not a universal solution so millage may vary, and perhaps it should not be recommended so highly.Trull
This code works in .net 5.0. And when I viewed the IL, it actually implements the swap, with an additional variable.Replay
Runs fine in Roslyn 3.8: dotnetfiddle.net/HgblydGirish
I
247

The right way to swap two variables, at the time this question was asked (1), is to use a temporary variable:

decimal tempDecimal = startAngle;
startAngle = stopAngle;
stopAngle = tempDecimal;

There you have it. No clever tricks, no maintainers of your code cursing you for decades to come, and no spending too much time trying to figure out why you needed it in one operation anyway since, at the lowest level, even the most complicated language feature is a series of simple operations.

Just a very simple, readable, easy to understand, temp = a; a = b; b = temp; solution.

In my opinion, developers who try to use tricks to, for example, "swap variables without using a temp" or "Duff's device" are just trying to show how clever they are (and failing miserably).

I liken them to those who read highbrow books solely for the purpose of seeming more interesting at parties (as opposed to expanding your horizons).

Solutions where you add and subtract, or the XOR-based ones, are less readable and most likely slower than a simple "temporary variable" solution (arithmetic/boolean-ops instead of plain moves at an assembly level).

Do yourself, and others, a service by writing good quality readable code.

That's my rant. Thanks for listening :-)

As an aside, I'm quite aware this doesn't answer your specific question (and I'll apologise for that) but there's plenty of precedent on SO where people have asked how to do something and the correct answer is "Don't do it".


(1) Improvements to the language and/or .NET Core since that time have adopted the "Pythonic" way using tuples. Now you can just do:

(startAngle, stopAngle) = (stopAngle, startAngle);

to swap values. This almost won't change the underlying operations but it at least has the small advantage of not having to introduce a temporary named variable to your code. And, in fact, you can see it still using a temporary variable (by pushing/popping values to/from the stack) under the covers, with an (a, b) = (b, a) statement:

IL_0005: ldloc.1  ; push b
IL_0006: ldloc.0  ; push a
IL_0007: stloc.2  ; t = pop (a)
IL_0008: stloc.0  ; a = pop (b)
IL_0009: ldloc.2  ; push t
IL_000a: stloc.1  ; b = pop (t)
Intimist answered 30/4, 2009 at 2:5 Comment(15)
+1; and for more reasons: with the +/- (etc) tricks you are doing unnecessary arithmetic. With integers, that may be just about acceptable at a push (the rounding/overflow aren't issues, and the CPU cost is virtually nil), but with decimals, add and subtract are non-trivial operations. It can't even use the FPU, as they aren't float/double. So use a temp variable already!!!Grandioso
of course this is the best way, but it was explicit asked without temp variableOlcott
+1 I agree with you. When you start complicating simple stuff you end up with all sort of problems to solve in the next few years...Gromme
Maybe there is a genuine reason for not using the temp variable. If the two variables are extremely big, you wouldn't want to create a new one hence having 3 extremely big in variables even not for long time.Doe
AFAIK, the problem it solved was how to unroll a loop in C, allowing for a non-integer multiplier on the first or last cycle. You can do that just as easily without reverting to Duff's Device, and in a much more readable way. If you think it solved a different problem that can't be solved more "readably", I'm open to being convinced. In any case, even if it solved a problem at some point in the past, it's almost never necessary nowadays, even on all but the puniest embedded systems.Intimist
It's worth adding that the right way in C# is to use a temp variable, but that's doesn't make it a universal fact. The idiomatic way in Python would be a, b = b ,aHorsecar
@tbone: in Python you virtually create some kind of tuple. That's the third value.Olcott
@CommuSoft temporary objects are not the same as temporary variables. right or wrong, that extra temp pollutes readability whereas the pythonic way is squeaky clean.Horsecar
@tbone: well actually a temporary variable never exists. It requires liveness analysis to determine when a variable is alive and that is the stage of the compiler where one takes temporary objects into account. At syntax level, a variables starts living at declaration and dies at the end of the method. There are only local and global variables...Olcott
@CommuSoft "Temporary variable" is not a language construct, there's no need for twisting words. This is about terseness and readability, not about compiler output or VM behaviour.Horsecar
"Don't do it" responses are one of the viruses of SO. The response assumes context and is not productive. The method of making a temporary variable is much less readable than tuple based approaches that allow a simple single line obvious and readable swap that is better and cleaner in every way than these temp variable approaches. Had he asked a bit later when that feature existed in C# maybe he would've gotten that productive answer rather than these useless rants that exist just to make the person stating them feel superior.Kohlrabi
Jeffrey, every answer to a question assumes some context, that's unavoidable. But "don't do it" answers are sometimes the best ones. If you use an unsorted variable record length text file as a multi-gigabyte database, you should be told it's a bad idea. And, before you start assigning motives to people, you may want to at least consider the possibility that some people do know more than others on certain subjects. I know I consider that to be so since I've asked questions here as well on areas I'm deficient in. That is, after all, what makes sites like this useful. ...Intimist
... I'll quite happily admit that Python's tuple assignment is by far the more readable way but C# didn't have that when the answer was posted. In any case, that readability does not carry over to the xor or add/sub methods - they are far less readable than a temp-var solution.Intimist
I completely disagree that this is the right way. Even the processor in your computer has xchg, which swaps two registers or memory locations in one clock cycle. If a language has a swap function that directly uses the xchg instruction, THAT is the right way. Using a temp variable takes slightly longer but it adds up if it's called millions of times in quick succession, like in an inner loop.Semang
iPaul, whether the cpu can do it is irrelevant, unless the language also supports it, since it's the language you're writing your code in. That is not the case here as you can see from the IL code, where it uses a temporary. It may be that JITting could be smart enough to do that but that's not a feature of the source code being written.Intimist
O
139

First of all, swapping without a temporary variable in a language as C# is a very bad idea.

But for the sake of answer, you can use this code:

startAngle = startAngle + stopAngle;
stopAngle = startAngle - stopAngle;
startAngle = startAngle - stopAngle;

Problems can however occur with rounding off if the two numbers differ largely. This is due to the nature of floating point numbers.

If you want to hide the temporary variable, you can use a utility method:

public static class Foo {

    public static void Swap<T> (ref T lhs, ref T rhs) {
        T temp = lhs;
        lhs = rhs;
        rhs = temp;
    }
}
Olcott answered 29/4, 2009 at 23:20 Comment(9)
That's fine for integers or fixed-point numbers. With floating point numbers you'll end up with minute rounding errors. They may or may not be big enough to matter, depends on how you're using the numbers.Monocyte
As long as you don't run into overflow issues, that works just finePalaestra
@Kennet Belenky: indeed, but i don't see another work around, except a temporary value. So I think it's the only "good" way to solve this problem. (Sorry for my English, if I made mistakes)Olcott
@Janusz Lenar: Well in languages with pointer manipulation you could use the same trick to swap the pointers. In C# you can do this in an unsafe environment. :D But anyway I admit swapping objects,ect. without a third variable is a bad idea (in reaction to this. __curious_geek). But the question said explicitly to do it without an extra variable.Olcott
This technique is more computationally expensive than using a temporary variable.Sentimental
Yes I know, but again, the question asked if it was possible to do it without a temporary variable. If you compile the code with a temporary variable, it probably won't even require additional memory since the temporary variable would only be stored in a register of the processor. But I suppose the question was homework or something equivalent.Olcott
I don't like the sentence "swapping without a temp variable is a very bad idea". Many languages support swapping variables in a clear way without the mistake-prone 3-line shuffle, so it's logical to ask if C# does. Python: a, b = b, a, C++: std::swap(a, b).Morin
@KevinS: Sure, some CPU's even have specific instructions or a macro for it. But using mathematical tricks to process it is not how it is supposed to be done. It is error-prone, is hard to understand. And for Python, what you do is create a tuple as a third variable. For C++'s swap you simply hide the third value in the method (or it is processed by the CPU directly). In case it is however not available, not using such variable is asking for trouble.Olcott
I'm not sure why the negative comment from paxdiablo. This solution is a very Functional and compact solution. And the method says what it does. So what is the problem with it??? Correction: A more functional approach now with Tuples is to do an inline swap. THAT is "the functional way". (a, b) = (b, a);Lenticular
O
77

Yes, use this code:

stopAngle = Convert.ToDecimal(159.9);
startAngle = Convert.ToDecimal(355.87);

The problem is harder for arbitrary values. :-)

Odey answered 29/4, 2009 at 23:31 Comment(0)
A
42
int a = 4, b = 6;
a ^= b ^= a ^= b;

Works for all types including strings and floats.

Antarctic answered 29/12, 2009 at 7:34 Comment(10)
I hope the XOR swap will be forgotten one day.Anastasio
XOR swap is near the pinnacle of nerdiness. I had nirvana for a couple days after learning it in school.Romilly
This does not seem to work at all #5577640Polash
At least add a comment so it is also understandable for the non-"binary ninja's"Capparidaceous
This is C#. The above code does not swap, as @zespri says. To your last sentence: In C# you cannot use the operator ^= with string or float, so it will not compile with them.Seibel
I believe this to be the pinnacle of nedriness. Guy assembles a working program in Pokemon by swapping items in inventory.Wherewithal
If I ever fly in a US govt. manufactured fighter jet, or have to have a pacemaker, etc., I seriously hope that I don't die because of a stackoverflow caused by some programmer who "hoped that XOR swap would be forgotten some day"Pyrogenic
1. In C# this does not work, see https://mcmap.net/q/181902/-c-loss-of-intermediate-values-in-multiple-assignment/1848953. 2. In all C-like languages it breaks when a and b contain an equal value because x ^ x == 0 (you lose the value in a and b). It is cool nerdy stuff to show a newbie programmer but why do people show the trick without teaching why it should never be used?Gupton
@ChrisBeck If a pacemaker or fighter jet broke because of a stack overflow, the problem isn't with using a 'proper' swap instead of an exor-swap, the problem is that the authors didn't use static analysis to check the maximum stack depth before shipping the code, in which case they should never have been allowed near such critical code in the first place and deserve to be fired. For that matter, exor-swap fails when both variables are equal, so using it would likely be introducing a delayed pacemaker-breaking/fighter-jet-breaking bug anyway.Guilt
> For that matter, exor-swap fails when both variables are equal Completely untruePyrogenic
S
27

BenAlabaster showed a practical way of doing a variable switch, but the try-catch clause is not needed. This code is enough.

static void Swap<T>(ref T x, ref T y)
{
     T t = y;
     y = x;
     x = t;
}

The usage is the same as he shown:

float startAngle = 159.9F
float stopAngle = 355.87F
Swap(ref startAngle, ref stopAngle);

You could also use an extension method:

static class SwapExtension
{
    public static T Swap<T>(this T x, ref T y)
    {
        T t = y;
        y = x;
        return t;
    }
}

Use it like this:

float startAngle = 159.9F;
float stopAngle = 355.87F;
startAngle = startAngle.Swap(ref stopAngle);

Both ways uses a temporary variable in the method, but you don't need the temporary variable where you do the swapping.

Sensory answered 5/3, 2013 at 18:17 Comment(4)
Yes, but only in the method, not where you do the switch.Sensory
Using an abstraction is a good way of solving the problem. It provides a general solution to a common problem and makes the calling code easier to read. Of course it uses a few extra bytes of memory and a few extra processor cycles, but unless you are calling this code millions of times, you won't notice any difference.Chadd
@OlivierJacot-Descombes, I hope if you call it a million times, the JIT will optimize it.Heirship
So the question is, why wasn't this handy function included in the .NET library? It's the first example given in the documentation for Generic Methods.Septuagenarian
D
18

A binary XOR swap with a detailed example:

XOR truth table:

a b a^b
0 0  0
0 1  1
1 0  1
1 1  0

Input:

a = 4;
b = 6;

Step 1: a = a ^ b

a  : 0100
b  : 0110
a^b: 0010 = 2 = a

Step 2: b = a ^ b

a  : 0010
b  : 0110
a^b: 0100 = 4 = b

Step 3: a = a ^ b

a  : 0010
b  : 0100
a^b: 0110 = 6 = a

Output:

a = 6;
b = 4;
Diphthong answered 29/4, 2009 at 23:9 Comment(0)
B
16

In C# 7:

(startAngle, stopAngle) = (stopAngle, startAngle);
Benares answered 29/9, 2017 at 13:39 Comment(0)
F
15

Not in C#. In native code you might be able to use the triple-XOR swap trick, but not in a high level type-safe language. (Anyway, I've heard that the XOR trick actually ends up being slower than using a temporary variable in many common CPU architectures.)

You should just use a temporary variable. There's no reason you can't use one; it's not like there's a limited supply.

Felker answered 29/4, 2009 at 23:13 Comment(4)
Most types that the XOR thing works for would fit in a register so the compiler shouldn't allocate stack space for it anyway.Protuberant
True, but it's more complex than that. You rarely need to swap values on a assembler level. The swapping can often be done as a side-effect of other arithmetic. Most of the time the swap is just required to express things in a high level language. After compiling the swap is no more and thus costs no time at all :-)Saeger
If memory is in short supply, such as on an embedded device, then temp variables are in short supply sometimes.Outdoor
@AsherMaximum: but it would be better if C# offered a way to swap two variables. Then this can be implemented with or without temp variable. By doing it explicitly, the code becomes unreadable and is hard to maintain.Olcott
S
14

For the sake of future learners, and humanity, I submit this correction to the currently selected answer.

If you want to avoid using temp variables, there are only two sensible options that take first performance and then readability into consideration.

  • Use a temp variable in a generic Swap method. (Absolute best performance, next to inline temp variable)
  • Use Interlocked.Exchange. (5.9 times slower on my machine, but this is your only option if multiple threads will be swapping these variables simultaneously.)

Things you should never do:

  • Never use floating point arithmetic. (slow, rounding and overflow errors, hard to understand)
  • Never use non-primitive arithmetic. (slow, overflow errors, hard to understand) Decimal is not a CPU primitive and results in far more code than you realize.
  • Never use arithmetic period. Or bit hacks. (slow, hard to understand) That's the compiler's job. It can optimize for many different platforms.

Because everyone loves hard numbers, here's a program that compares your options. Run it in release mode from outside Visual Studio so that Swap is inlined. Results on my machine (Windows 7 64-bit i5-3470):

Inline:      00:00:00.7351931
Call:        00:00:00.7483503
Interlocked: 00:00:04.4076651

Code:

class Program
{
    static void Swap<T>(ref T obj1, ref T obj2)
    {
        var temp = obj1;
        obj1 = obj2;
        obj2 = temp;
    }

    static void Main(string[] args)
    {
        var a = new object();
        var b = new object();

        var s = new Stopwatch();

        Swap(ref a, ref b); // JIT the swap method outside the stopwatch

        s.Restart();
        for (var i = 0; i < 500000000; i++)
        {
            var temp = a;
            a = b;
            b = temp;
        }
        s.Stop();
        Console.WriteLine("Inline temp: " + s.Elapsed);


        s.Restart();
        for (var i = 0; i < 500000000; i++)
        {
            Swap(ref a, ref b);
        }
        s.Stop();
        Console.WriteLine("Call:        " + s.Elapsed);

        s.Restart();
        for (var i = 0; i < 500000000; i++)
        {
            b = Interlocked.Exchange(ref a, b);
        }
        s.Stop();
        Console.WriteLine("Interlocked: " + s.Elapsed);

        Console.ReadKey();
    }
}
Sliwa answered 18/7, 2014 at 16:28 Comment(2)
Bit hacks are actually not slow at all. For instance in order to load 0 into a register, a compiler will xor the variable with itself because the instruction is shorter. In some rare occasions by using less variables, one avoids register spilling. It is the compilers job, but it is unfortunate that there is no language support to do this efficiently.Olcott
You're right. In cases where this is a hotspot and speed matters that badly, you are going to need to go unmanaged. Bit hacks often backfire in managed languages. That's really the responsibility of the jitter.Sliwa
R
7

<deprecated>

You can do it in 3 lines using basic math - in my example I used multiplication, but simple addition would work also.

float startAngle = 159.9F;
float stopAngle = 355.87F;

startAngle = startAngle * stopAngle;
stopAngle = startAngle / stopAngle;
startAngle = startAngle / stopAngle;

Edit: As noted in the comments, this wouldn't work if y = 0 as it would generate a divide by zero error which I hadn't considered. So the +/- solution alternatively presented would be the best way to go.

</deprecated>


To keep my code immediately comprehensible, I'd be more likely to do something like this. [Always think about the poor guy that's gonna have to maintain your code]:

static bool Swap<T>(ref T x, ref T y)
{
    try
    {
        T t = y;
        y = x;
        x = t;
        return true;
    }
    catch
    {
        return false;
    }
}

And then you can do it in one line of code:

float startAngle = 159.9F
float stopAngle = 355.87F
Swap<float>(ref startAngle, ref stopAngle);

Or...

MyObject obj1 = new MyObject("object1");
MyObject obj2 = new MyObject("object2");
Swap<MyObject>(ref obj1, ref obj2);

Done like dinner...you can now pass in any type of object and switch them around...

Region answered 29/4, 2009 at 23:32 Comment(7)
little bit equal to my solution, but notice that multiplications and division operation cost a lot of CPU-time. And the upper- and lower-bounds of a float are more easy to reach with multiplication.Olcott
What do you mean with "Decimal doesn't allow for decimal places"? That sounds confusing as the decimal type does represent real numbers with a high precision (decimal d = 9.1m; is perfectly valid in C#).Alic
and what if one of the variables is zero (or both), the second division will cause an error (division by zero). And the function created could better return false to warn the user, that the swap operation wasn't completed.Olcott
@divo: I stand corrected... I must've missed that class, I'd been trying to assign Decimal n = 9.1; and it just gives me a compiler error. Missed the M on the end :P Answer modified accordingly.Region
@CommuSoft: Point taken, I hadn't considered that. In that case, the +/- would surely be the better way to go.Region
What's up with your swap method? Why does it return a bool, why is that bool always true (if it exists)? Why does it swallow all exceptions (which could only be a ThreadAbortException in this case, I believe, since it doesn't allocate memory or enlarge the call stack)?Burnley
Simple, strongly typed assignements not involving array variance will never throw exceptions. Type mismatches will be caught at compile time (this is what strong typing is about).Chadd
D
7

With C# 7, you can use tuple deconstruction to achieve the desired swap in one line, and it's clear what's going on.

decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);

(startAngle, stopAngle) = (stopAngle, startAngle);
Driver answered 22/7, 2017 at 1:12 Comment(0)
S
6

For completeness, here is the binary XOR swap:

int x = 42;
int y = 51236;
x ^= y;
y ^= x;
x ^= y;

This works for all atomic objects/references, as it deals directly with the bytes, but may require an unsafe context to work on decimals or, if you're feeling really twisted, pointers. And it may be slower than a temp variable in some circumstances as well.

Seasick answered 1/5, 2009 at 9:42 Comment(0)
T
5

If you can change from using decimal to double you can use the Interlocked class. Presumably this will be a good way of swapping variables performance wise. Also slightly more readable than XOR.

var startAngle = 159.9d;
var stopAngle = 355.87d;
stopAngle = Interlocked.Exchange(ref startAngle, stopAngle);

Msdn: Interlocked.Exchange Method (Double, Double)

Topaz answered 30/7, 2013 at 7:39 Comment(0)
A
4
a = a + b
b = a - b
a = a - b

َ

Aero answered 5/7, 2009 at 17:40 Comment(0)
T
4

Beware of your environment!

For example, this doesn’t seem to work in ECMAscript

y ^= x ^= y ^= x;

But this does

x ^= y ^= x; y ^= x;

My advise? Assume as little as possible.

Trismus answered 8/10, 2010 at 3:21 Comment(2)
Even on c, if pointers are involved (e.g in function) *a ^= *b ^= *a ^= *b does not work (local variable however works e.g c ^= d ^= c ^= d), but *a ^= *b ^= *a; *b ^= *a; works. My choice thus would be to use *a ^= *b; *b ^= *a; *a ^= *b; which works perfectly.Orcinol
How is ECMAscript relevant? The question is tagged C#.Carrollcarronade
K
3

The simple way to swap 2 numbers in just one line:

a=(a+b)-(b=a);

eg: a=1, b=2

Step 1: a=(1+2) - (b=1)

Step 2: a=3-1

=> a=2 and b=1


Efficient way is to use:

C Programming: (x ^= y), (y ^= x), (x ^= y);

Java: x = x ^ y ^ (y = x);

Python: x, y = y, x

Note: Most common mistake people make: //Swap using bitwise XOR (Wrong Solution in C/C++)

x ^= y ^= x ^= y; 

Source: GeeksforGeek

Kalmuck answered 5/5, 2016 at 20:58 Comment(1)
proper c++: std::swap(x, y);.Surety
S
3

Sometimes I wish it were possible to write a function in MSIL inline in C#, similar to how you can write inline assembler in C.

For the record, I once wrote a helper library for C# with various functions for things that were impossible to write in C# but can be written in MSIL (non-zero-based arrays for example). I had this function:

.method public hidebysig static void Swap<T> (
        !!T& a,
        !!T& b
    ) cil managed 
{
    .maxstack 4

    ldarg.1      // push a& reference
    ldarg.2      // push b& reference
    ldobj !!T    // pop b&, push b
    ldarg.2      // push b& reference
    ldarg.1      // push a& reference
    ldobj !!T    // pop a&, push a
    stobj !!T    // store a in b&
    stobj !!T    // store b in a&
    ret
}

And no locals needed. Of course this was just me being silly...

Sanguinary answered 30/1, 2021 at 23:33 Comment(2)
AFAIK with reflection you can create such function from IL instructions.Gilbertina
Yes obviously, but then you need to compile it every time you run the app. Anyway why would you bother? It was just for fun.Sanguinary
W
2

I hope this might help...

using System;

public class Program
{
    public static void Main()
    {
        int a = 1234;
        int b = 4321;

        Console.WriteLine("Before: a {0} and b {1}", a, b);

        b = b - a;
        a = a + b;
        b = a - b;

        Console.WriteLine("After: a {0} and b {1}", a, b);
    }
}
Woodrow answered 15/3, 2016 at 23:49 Comment(0)
R
2

we can do that by doing a simple trick

a = 20;
b = 30;
a = a+b; // add both the number now a has value 50
b = a-b; // here we are extracting one number from the sum by sub
a = a-b; // the number so obtained in above help us to fetch the alternate number from sum
System.out.print("swapped numbers are a = "+ a+"b = "+ b);
Raymonderaymonds answered 30/6, 2017 at 17:37 Comment(0)
P
1

For binary types you can use this funky trick:

a %= b %= a %= b;

As long as a and b are not the exact same variable (e.g. aliases for the same memory) it works.

Protuberant answered 29/4, 2009 at 23:25 Comment(0)
S
1
startAngle = (startAngle + stopAngle) - (stopAngle = startAngle);
Soapbark answered 14/2, 2015 at 9:30 Comment(0)
B
0

If you want to swap 2 string variables:

a = (a+b).Substring((b=a).Length);

An helper method accordingly:

public static class Foo {
    public static void SwapString (ref string a, ref string b) {
       a = (a+b).Substring((b=a).Length);
    }
}

Usage would be then:

string a="Test 1";
string b="Test 2";
Foo.SwapString(a, b);
Blondy answered 30/8, 2017 at 14:7 Comment(3)
Oh dear god what is that :PLeann
@Leann - Any comments to take serious?Blondy
Huh? What do you mean?Leann
D
0

Heres another swap function

public static void Flip(ref int a, ref int b)
{            
    b = b + a;
    a = b - (b - (b - a));
    b = -1 * (a - (a - (a - b))); 
}
Disembark answered 14/7, 2023 at 22:57 Comment(1)
Thank you for your interest in contributing to the Stack Overflow community. This question already has quite a few answers—including one that has been extensively validated by the community. Are you certain your approach hasn’t been given previously? If so, it would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient. Can you kindly edit your answer to offer an explanation?Characterize
H
-1

Here another approach in one line:

decimal a = 159.9m;
decimal b = 355.87m;

a = b + (b = a) - b;
Hundred answered 24/3, 2017 at 12:46 Comment(0)
H
-1

Here is some different process to swap two variables

//process one
a=b+a;
b=a-b;
a=a-b;
printf("a= %d  b=  %d",a,b);

//process two
a=5;
b=10;
a=a+b-(b=a);
printf("\na= %d  b=  %d",a,b);

//process three
a=5;
b=10;
a=a^b;
b=a^b;
a=b^a;
printf("\na= %d  b=  %d",a,b);

//process four
a=5;
b=10;
a=b-~a-1;
b=a+~b+1;
a=a+~b+1;
printf("\na= %d  b=  %d",a,b);
Herringbone answered 11/8, 2017 at 19:16 Comment(0)
F
-1

this model is very useful

        var a = 10;
        var b = 20;

        (int a,int b)  c = (a,b);

        a = c.b ;
        b = c.a ;
Ferrari answered 11/9, 2021 at 14:42 Comment(0)
L
-2
var a = 15;
var b = -214;
a = b | !(b = a);

This works great.

Leftover answered 30/3, 2013 at 13:52 Comment(0)
I
-4

Very simple code for swapping two variables:

static void Main(string[] args)
{
    Console.WriteLine("Prof.Owais ahmed");
    Console.WriteLine("Swapping two variables");

    Console.WriteLine("Enter your first number ");
    int x = Convert.ToInt32(Console.ReadLine());

    Console.WriteLine("Enter your first number ");
    int y = Convert.ToInt32(Console.ReadLine());

    Console.WriteLine("your vlaue of x is="+x+"\nyour value of y is="+y);

    int z = x;
    x = y;
    y = z;

    Console.WriteLine("after Swapping value of x is="+x+"/nyour value of y is="+y);
    Console.ReadLine();
}
Inmesh answered 9/8, 2015 at 8:7 Comment(2)
Pretty sure that z counts as a temp variable here.Dermato
@Dermato if you move it out of function and make static It wont be temp anymore lolToneme
M
-6

You can try the following code. It is much more better than the other code.

a = a + b;
b = a - b;
a = a - b;
Mendez answered 23/6, 2016 at 8:48 Comment(1)
This is exactly the same as several of the other answers. Some of which were added already 7 years ago!Starkey

© 2022 - 2024 — McMap. All rights reserved.