76

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
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Sreedhar
  • 26,251
  • 31
  • 104
  • 163
  • 33
    This news article relates: [Govt bans StackOverflow.com; Developer takes 6 hours to swap 2 variables](http://www.theunrealtimes.com/2015/01/07/govt-bans-stackoverflow-com-developer-takes-6-hours-to-swap-2-variables/) – Basic Apr 15 '15 at 23:39
  • Refer my answer by clicking following link. [Swapping two numbers using only two variables](http://stackoverflow.com/a/42289828/4629101). – Pankaj Lilan Feb 17 '17 at 05:10
  • 1
    decimal stopAngle = Convert.ToDecimal(159.9); decimal startAngle = Convert.ToDecimal(355.87); –  Oct 10 '17 at 09:49
  • 1
    I suggest choosing the answer provided by @TimothyP about C# 7 tuples as the new accepted answer. It is now the most pragmatic way to accomplish your goal. – Brandon Bonds Dec 28 '17 at 17:41
  • *Never* convert a floating point to a decimal. It should be string, not a floating point, e.g. Convert.ToDecimal("159.9") – JoelFan Oct 18 '20 at 19:05
  • I would have thought that article was an April fool's joke, or maybe The Onion – StayOnTarget Apr 20 '21 at 12:46

29 Answers29

221

The right way to swap two variables is:

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

In other words, use a temporary variable.

There you have it. No clever tricks, no maintainers of your code cursing you for decades to come, no entries to The Daily WTF, 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, t = a; a = b; b = t; 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 "temp 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".

paxdiablo
  • 772,407
  • 210
  • 1,477
  • 1,841
  • 8
    +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!!! – Marc Gravell Apr 30 '09 at 07:43
  • 5
    of course this is the best way, but it was explicit asked without temp variable – Willem Van Onsem Apr 30 '09 at 11:52
  • +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... – Nelson Reis May 01 '09 at 10:16
  • 2
    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. – koumides Jul 07 '12 at 19:15
  • 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. – paxdiablo Jul 30 '13 at 08:02
  • 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 ,a – tbone Feb 01 '15 at 17:33
  • @tbone: in Python you virtually create some kind of tuple. That's the third value. – Willem Van Onsem Feb 26 '15 at 16:16
  • @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. – tbone Mar 17 '15 at 19:43
  • @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... – Willem Van Onsem Mar 17 '15 at 19:52
  • @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. – tbone Mar 17 '15 at 21:18
  • "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. – Jeffrey Vest Apr 08 '19 at 18:54
  • 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. ... – paxdiablo Apr 08 '19 at 21:55
  • ... 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. – paxdiablo Apr 08 '19 at 21:59
172

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.

Colonel Panic
  • 119,181
  • 74
  • 363
  • 435
TimothyP
  • 18,775
  • 23
  • 88
  • 141
  • 9
    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. – Jeffrey Vest Apr 08 '19 at 18:57
  • How performant is this though? I always fear some "Tuple" instance created on the heap internally and all those fancy things happening. – Ray Oct 25 '19 at 21:44
  • 7
    @Ray https://www.reddit.com/r/ProgrammerTIL/comments/8ssiqb/cyou_can_swap_values_of_two_variable_with_the_new/e12301f/ – prime23 Oct 30 '19 at 02:53
  • -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. https://ideone.com/03zt9U – TheBeardedQuack Mar 03 '20 at 14:55
  • 1
    @TheBeardedQuack Your link show correct results. Why you say it does not work with primitive types? – AlexWei Apr 02 '20 at 13:40
  • No it doens't... It shoes `a` and `b` both equal to 10 after instead of a successful swap. – TheBeardedQuack Apr 02 '20 at 13:59
  • @TheBeardedQuack 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 compiler – TimothyP Apr 03 '20 at 08:31
  • 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. – TheBeardedQuack Apr 03 '20 at 10:13
  • 1
    This code works in .net 5.0. And when I viewed the IL, it actually implements the swap, with an additional variable. – Raj Rao Feb 16 '21 at 04:52
  • Runs fine in Roslyn 3.8: https://dotnetfiddle.net/Hgblyd – Mass Dot Net May 17 '21 at 04:42
128

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;
    }
}
scharette
  • 7,629
  • 6
  • 25
  • 58
Willem Van Onsem
  • 321,217
  • 26
  • 295
  • 405
  • 36
    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. – Kennet Belenky Apr 29 '09 at 23:32
  • 7
    As long as you don't run into overflow issues, that works just fine – patjbs Apr 29 '09 at 23:33
  • @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) – Willem Van Onsem Apr 29 '09 at 23:37
  • 148
    The only *good* way to solve this problem is to use a temp variable. "Clever" code like this (and, by "clever", I mean "stupid") is far less readable and obvious than the temp-variable solution. If I saw code like this from one of my minions, they'd be subject to sanctions and sent back to do it right. I'm not having a go at you specifically, @CommuSoft (since you answered the question), but the question itself was rubbish. – paxdiablo Apr 30 '09 at 00:01
  • 4
    @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. – Willem Van Onsem Sep 18 '11 at 12:13
  • 14
    This technique is more computationally expensive than using a temporary variable. – Mike Dec 29 '12 at 15:21
  • 3
    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. – Willem Van Onsem Jan 05 '13 at 23:59
  • 4
    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)`. – Kevin S Feb 12 '15 at 15:31
  • @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. – Willem Van Onsem Feb 12 '15 at 15:34
  • Just adding for future me when I search the same issue, that I have already created a class: public static class NakdHelper { public static void Swap(ref T firstValue, ref T secondValue) { T temp = firstValue; firstValue = secondValue; secondValue = temp; } } – Igor Jovanoski Dec 18 '19 at 11:42
  • 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); – Richard Keene Aug 13 '20 at 21:10
74

Yes, use this code:

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

The problem is harder for arbitrary values. :-)

Willem Van Onsem
  • 321,217
  • 26
  • 295
  • 405
Paul Sonier
  • 36,435
  • 3
  • 72
  • 113
44
int a = 4, b = 6;
a ^= b ^= a ^= b;

Works for all types including strings and floats.

Willem Van Onsem
  • 321,217
  • 26
  • 295
  • 405
this. __curious_geek
  • 40,897
  • 20
  • 108
  • 134
  • 23
    I hope the XOR swap will be forgotten one day. – helpermethod Oct 12 '10 at 10:30
  • 9
    XOR swap is near the pinnacle of nerdiness. I had nirvana for a couple days after learning it in school. – Gabriel Magana Nov 06 '10 at 13:25
  • 9
    This does not seem to work at all http://stackoverflow.com/questions/5577140/why-does-swapping-values-with-xor-fail-when-using-this-compound-form – Andrew Savinykh Jul 28 '13 at 22:48
  • At least add a comment so it is also understandable for the non-"binary ninja's" – Mike de Klerk Dec 15 '14 at 07:38
  • 3
    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. – Jeppe Stig Nielsen Apr 09 '15 at 10:50
  • 1
    I believe [this](http://aurellem.org/vba-clojure/html/total-control.html) to be the pinnacle of nedriness. Guy assembles a working program in Pokemon by swapping items in inventory. – rr- Jun 26 '15 at 10:00
  • 5
    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" – Chris Beck Aug 22 '15 at 21:58
22

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.

Marcus
  • 393
  • 3
  • 6
  • 2
    Yes, but only in the method, not where you do the switch. – Marcus Mar 05 '13 at 18:29
  • 3
    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. – Olivier Jacot-Descombes Oct 27 '13 at 14:10
  • @OlivierJacot-Descombes, I hope if you call it a million times, the JIT will optimize it. – Sebastian Jan 07 '14 at 14:57
  • 2
    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](https://msdn.microsoft.com/en-us/library/twcad0zb.aspx). – Mark Ransom Jun 24 '15 at 20:30
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;
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Steven Muhr
  • 3,181
  • 23
  • 43
13

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();
    }
}
jnm2
  • 7,157
  • 5
  • 57
  • 92
  • 1
    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. – Willem Van Onsem May 20 '15 at 21:42
  • 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. – jnm2 May 20 '15 at 23:46
13

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.

Jens Alfke
  • 1,816
  • 12
  • 12
  • Most types that the XOR thing works for would fit in a register so the compiler shouldn't allocate stack space for it anyway. – BCS Apr 29 '09 at 23:27
  • 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 :-) – Nils Pipenbrinck Apr 29 '09 at 23:31
  • If memory is in short supply, such as on an embedded device, then temp variables are in short supply sometimes. – AsherMaximum Jul 18 '13 at 20:49
  • @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. – Willem Van Onsem Feb 26 '15 at 17:06
11

In C# 7:

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

<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...

BenAlabaster
  • 36,299
  • 19
  • 100
  • 147
  • 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. – Willem Van Onsem Apr 29 '09 at 23:51
  • 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#). – Dirk Vollmar Apr 29 '09 at 23:57
  • 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. – Willem Van Onsem Apr 30 '09 at 00:01
  • @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. – BenAlabaster Apr 30 '09 at 00:01
  • 1
    @CommuSoft: Point taken, I hadn't considered that. In that case, the +/- would surely be the better way to go. – BenAlabaster Apr 30 '09 at 00:02
  • 2
    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)? – Doug McClean Jul 05 '09 at 18:07
  • 1
    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). – Olivier Jacot-Descombes Oct 27 '13 at 14:24
7

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.

thecoop
  • 42,842
  • 15
  • 122
  • 181
6

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)

Robert Fricke
  • 3,499
  • 17
  • 32
6

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);
jdphenix
  • 13,519
  • 3
  • 37
  • 68
4
a = a + b
b = a - b
a = a - b

َ

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
4

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

Utsav Dusad
  • 1,933
  • 4
  • 24
  • 52
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.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Codzart
  • 57
  • 1
  • 1
  • 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. – Pramod Oct 06 '12 at 13:17
  • 2
    How is ECMAscript relevant? The question is tagged C#. – Peter Mortensen Sep 16 '16 at 03:31
4

With tuples

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

(startAngle, stopAngle) = (stopAngle, startAngle);
Zu1779
  • 2,080
  • 1
  • 17
  • 17
3

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);
    }
}
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
PalakM
  • 244
  • 1
  • 16
3

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.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
BCS
  • 67,242
  • 64
  • 175
  • 277
2
startAngle = (startAngle + stopAngle) - (stopAngle = startAngle);
Ayub
  • 1,705
  • 21
  • 27
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);
cammando
  • 528
  • 7
  • 19
1

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);
HGMamaci
  • 1,184
  • 11
  • 19
0

Here another approach in one line:

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

a = b + (b = a) - b;
fubo
  • 39,783
  • 16
  • 92
  • 127
0

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);
A.A Noman
  • 4,233
  • 9
  • 23
  • 38
0

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...

Charlieface
  • 8,963
  • 1
  • 6
  • 23
-1
var a = 15;
var b = -214;
a = b | !(b = a);

This works great.

segavu
  • 15
  • 1
-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();
}
Calcolat
  • 838
  • 2
  • 11
  • 21
-4

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

a = a + b;
b = a - b;
a = a - b;
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
as7
  • 1
  • 2
  • 5
    This is *exactly* the same as several of the other answers. Some of which were added already 7 years ago! – Bo Persson Jun 23 '16 at 09:16