Most of the answers here are pretty old, and since then C# has been updated with the ability to allocate memory on stack instead of heap. Using stackalloc allows us to write more efficient code that does not allocate any memory which needs to be cleaned up afterwards.
public static uint GetIPV4AddressUint(IPAddress ipAddr)
{
if (ipAddr.AddressFamily is not AddressFamily.InterNetwork) throw new InvalidOperationException("GetIPV4Adress supports only ipv4 addresses");
Span<byte> addrBytes = stackalloc byte[4];
if (!ipAddr.TryWriteBytes(addrBytes, out int _)) throw new InvalidDataException("Unable to get ip address bytes");
return ((uint)addrBytes[3] << 24) + ((uint)addrBytes[2] << 16) + ((uint)addrBytes[1] << 8) + addrBytes[0];
}
Benchmark (using BenchmarkDotNet, .NET6)
[Benchmark]
public uint GetIPV4AddressUint_Stackalloc()
{
IPAddress ipAddr = IPAddress.Any;
if (ipAddr.AddressFamily is not AddressFamily.InterNetwork) throw new InvalidOperationException("GetIPV4Adress supports only ipv4 addresses");
Span<byte> addrBytes = stackalloc byte[4];
if (!ipAddr.TryWriteBytes(addrBytes, out int _)) throw new InvalidDataException("Unable to get ip address bytes");
return ((uint)addrBytes[3] << 24) + ((uint)addrBytes[2] << 16) + ((uint)addrBytes[1] << 8) + addrBytes[0];
}
[Benchmark]
public uint GetIPV4AddressUint_ByteArray_TryWriteBytes()
{
IPAddress ipAddr = IPAddress.Any;
if (ipAddr.AddressFamily is not AddressFamily.InterNetwork) throw new InvalidOperationException("GetIPV4Adress supports only ipv4 addresses");
byte[] addrBytes = new byte[4];
if (!ipAddr.TryWriteBytes(addrBytes, out int _)) throw new InvalidDataException("Unable to get ip address bytes");
return ((uint)addrBytes[3] << 24) + ((uint)addrBytes[2] << 16) + ((uint)addrBytes[1] << 8) + addrBytes[0];
}
[Benchmark]
public uint GetIPV4AddressUint_ByteArray_GetAddressBytes()
{
IPAddress ipAddr = IPAddress.Any;
if (ipAddr.AddressFamily is not AddressFamily.InterNetwork) throw new InvalidOperationException("GetIPV4Adress supports only ipv4 addresses");
byte[] addrBytes = ipAddr.GetAddressBytes();
return ((uint)addrBytes[3] << 24) + ((uint)addrBytes[2] << 16) + ((uint)addrBytes[1] << 8) + addrBytes[0];
}
Benchmark results
| Method |
Mean |
Error |
StdDev |
Median |
Allocated |
| GetIPV4AddressUint_Stackalloc |
5.096 ns |
0.1577 ns |
0.4576 ns |
5.119 ns |
- |
| GetIPV4AddressUint_ByteArray_TryWriteBytes |
9.663 ns |
0.2761 ns |
0.7879 ns |
9.403 ns |
32 B |
| GetIPV4AddressUint_ByteArray_GetAddressBytes |
7.885 ns |
0.1756 ns |
0.1643 ns |
7.877 ns |
32 B |