5 ways to swap 2 variables in C#

Code Computerlove
5 min readMar 7, 2023

How to swap the values of two variables has long been a staple of technical interviews. A simple question aimed at weeding out those who can talk the talk but aren’t yet at the walking stage. But like most things in software, there is more than one way to skin a cat.

To formalise what we’re trying to achieve, we start with two variables:

int a = 3;
int b = 5;

We want to end up with them reversed:

a == 5; // true
b == 3; // true

1. Using a third variable

Let’s start with the obvious approach, the one people will expect from you in an interview — using a third variable:

int a = 3;
int b = 5;
int temp = a;
a = b;
b = temp;

Hopefully this doesn’t look too mind blowing. A simple shuffling of values. a copied to temp, b copied to a, and temp copied to b. The IL for the above contains no surprises:

// int a = 3
IL_0001: ldc.i4.3
IL_0002: stloc.0 // a
// int b = 5
IL_0003: ldc.i4.5
IL_0004: stloc.1 // b
// int temp = a
IL_0005: ldloc.0 // a
IL_0006: stloc.2 // temp
// a = b
IL_0007: ldloc.1 // b
IL_0008: stloc.0 // a
// b = temp
IL_0009: ldloc.2 // temp
IL_000a: stloc.1 // b

2. Being a clever clogs with addition and subtraction

Those with a bit of maths knowledge might realise that they can get a bit tricksy using addition and subtraction to avoid using a third variable:

int a = 3;
int b = 5;
a = a + b;
b = a - b;
a = a - b;

We are definitely in clever clogs territory here but at the same time there’s no programming trickery, just basic maths. Once again, no surprises in the IL:

// int a = 3
IL_0001: ldc.i4.3
IL_0002: stloc.0 // a
// int b = 5
IL_0003: ldc.i4.5
IL_0004: stloc.1 // b
// a = a + b
IL_0005: ldloc.0 // a
IL_0006: ldloc.1 // b
IL_0007: add
IL_0008: stloc.0 // a
// b = a - b
IL_0009: ldloc.0 // a
IL_000a: ldloc.1 // b
IL_000b: sub
IL_000c: stloc.1 // b
// a = a - b
IL_000d: ldloc.0 // a
IL_000e: ldloc.1 // b
IL_000f: sub
IL_0010: stloc.0 // a

3. Being too much of a clever clogs with multiplication and division

If it works for addition and subtraction, then it should work for multiplication and division:

int a = 3;
int b = 5;
a = a * b;
b = a / b;
a = a / b;

There’s just one small problem:

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:01.93] Tests.Switch two variables using multiplication and division [FAIL]
Failed Tests.Switch two variables using multiplication and division [10 ms]
Error Message:
FsCheck.Xunit.PropertyFailedException :
Falsifiable, after 1 test (0 shrinks) (StdGen (1196671128, 297120679)):
Original:
(0, 0)
---- System.DivideByZeroException : Attempted to divide by zero.

Whoops. If b is 0 then we get a divide by zero exception. Trying to be a smart-arse and falling on your sword is just embarrassing 🤦‍♂️.

4. XOR

XOR all the things. It’s clever. It’s silly. But still definitely clever.

int a = 3;
int b = 5;
a = a ^ b;
b = a ^ b;
a = a ^ b;

If you don’t use bitwise operations very often (I don’t) then this can look a bit magical so let’s break it down. XOR is one of the 3 binary logical operations:

Input 1Input 2& (logical AND)| (logical OR)^ (logical exclusive OR)11110100110101100000

Starting with:

a = 3 = 0 1 1
b = 5 = 1 0 1

XOR them together and assign to a:

a   0 1 1 (3)
b 1 0 1 (5)
-----
a = 1 1 0 (6 for what it's worth)

XOR again and assign to b:

a   1 1 0 (6)
b 1 0 1 (5)
-----
b = 0 1 1 (3)

And finally XOR again and assign to a:

a   1 1 0 (6)
b 0 1 1 (3)
-----
a = 1 0 1 (5)

5. Tuple deconstruction

We’ve seen a couple of ways to swap variables. In order for them not to be silly they’d need to improve readability. Going back and reading the examples again, none of them are better than the vanilla, third variable approach. In fact, I’d say they’re fairly obtuse. But there is an approach which I think is a slight improvement.

First, a little bit of history. C# 4 introduced tuples (rhymes with multiples). A type to hold multiple values. To be honest, they were kind of clunky:

var foo = new Tuple<int, int>(1, 2);
Console.WriteLine($"foo contains {foo.Item1} and {foo.Item2}");
// foo contains 1 and 2

Fast forward to C# 7 and a new, cleaner syntax for constructing tuples was introduced:

var foo = (1, 2);

And a nice way to get values out of a tuple using de-structuring (a bit like using a constructor in reverse):

var (x, y) = foo;
x == 1; // true
y == 2; // true

Combining the constructor and de-structure into one line allows us to switch two variables in a beautifully concise way:

int a = 3;
int b = 5;
(b, a) = (a, b);

I could actually imagine myself writing this and think it’s an improvement over the third variable approach but then again, I write F# for fun so your mileage may vary 🙂.

Of course, like many C# language features over the years, this is all syntactic sugar. A quick check of the IL reveals…

// int a = 3 
IL_0001: ldc.i4.3
IL_0002: stloc.0 // a
// int b = 5
IL_0003: ldc.i4.5
IL_0004: stloc.1 // b
// (b, a) = (a, b)
IL_0005: ldloc.0 // a
IL_0006: ldloc.1 // b
IL_0007: stloc.2 // V_2
IL_0008: stloc.1 // b
IL_0009: ldloc.2 // V_2
IL_000a: stloc.0 // a

…a third variable, V_2! This is functionally identical to approach 1 above.

But hey! I think it’s more readable and the point of code is to be readable. Honestly, the CLR couldn’t care less which approach you use but other developers, and future you, will be thankful for clean, habitable, readable code.

Also, it might impress someone in an interview 😉.

--

--

Code Computerlove

Code Computerlove are a digital product agency, making brilliant digital experiences since 1999.