From the LINZ website (NZ mapping body):
"NZMG is not based on a geometric projection (transverse Mercator is based on a cylinder). Instead it uses a complex-number polynomial expansion. This has the advantage of exhibiting minimal scale distortion over New Zealand; however it is a projection unique to New Zealand and so can be difficult to use or program into computer software or positioning devices. "
In packages such as ESRI ArcGIS you can reproject data easily...... however if you're writting your own software you need to find some libraries to do this.
PROJ4 is one such library. It can be downloaded with GDAL / OGR as part of FW TOOLS.
Here there are 2 tools to assist in transformations... PROJ and CS2CS.
CS2CS caters with changes in DATUM.
To convert from NZMG to WGS84 requires a change in datum.
There are 3 methods to do this...
a) 3 parameter shift
b) 7 parameter shift
c) grid (NTv2)
a) is only good to the nearest 100m or so...
b) is only good to 5m or so..
c) uses a look up grid and should be good to nearest few cm
The look up grid can be downloaded from here: ftp://ftp.remotesensing.org/proj
Syntax to convert a user entered co-ordinate from WGS84 lat/long to NZMG x,y (m):
C:\Program Files\FWTools2.1.0\bin>cs2cs +proj=latlong +datum=WGS84 +to +proj=nzmg +datum=nzgd49 +nadgrids=o:/nzgd2kgrid0005.gsb
170 -43 [enter]
2265438.60 5796423.71 0.00
This should give you metre accuracte conversions.
To carry out from C# using FW TOOLS... you will need to check the C# example from Tamas Szekeres. This can be found in the FWTOOLS / csharp /apps folder.. and is entitled OSRTransform.cs.
A few modifications are required to work with NZMG and WGS84... as follows:
OSGeo.OSR.SpatialReference src = new OSGeo.OSR.SpatialReference("");
OSGeo.OSR.SpatialReference dst = new OSGeo.OSR.SpatialReference("");
dst.ImportFromProj4("+proj=nzmg +x_0=25100000.0000000000 +y_0=6023150.0000000000 +datum=nzgd49 +nadgrids='o:\nzgd2kgrid0005.gsb'");
CoordinateTransformation ct = new OSGeo.OSR.CoordinateTransformation(src, dst);
double p = new double;
p = 172.585303;
p = -43.510183;
p=0; //needed even if 0 value
ct.TransformPoint(p); Console.WriteLine("x:" + p + " y:" + p) ;___
This should give you results accurate to a few metres.