protected override Array ReadData(int[] origin, int[] stride, int[] shape)
        {
            // TODO: there is a problem using nc_get_vars_string!!!
            // remove this trick:
            if (TypeOfData == typeof(string))
            {
                return(base.ReadData(origin, stride, shape));
            }

            if (origin == null)
            {
                origin = new int[Rank];
            }

            if (shape == null)
            {
                shape = ReadShape();
                for (int i = 0; i < shape.Length; i++)
                {
                    shape[i] -= origin[i];
                }
            }
            if (stride == null)
            {
                origin = new int[Rank];
                for (int i = 0; i < Rank; i++)
                {
                    stride[i] = 1;
                }
            }
            if (Rank == 0)
            {
                shape = new int[] { 1 }
            }
            ;                                            // the place for data

            // Total number of elements in the array
            int n = 1;

            for (int i = 0; i < shape.Length; i++)
            {
                n *= shape[i];
            }

            int res;

            switch (Type.GetTypeCode(TypeOfData))
            {
            case TypeCode.Boolean:
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(bool), Rank == 0 ? new int[1] : new int[Rank]));
                }
                byte[] blData = new byte[n];
                res = NetCDF.nc_get_vars_ubyte(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), blData);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArrayBool(blData, shape));

            case TypeCode.DateTime:
                double[] dtData = new double[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(DateTime), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_double(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), dtData);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArrayDateTime(dtData, shape));

            case TypeCode.Double:
                double[] data = new double[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(double), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_double(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), data);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(data, shape));

            case TypeCode.Single:
                float[] fdata = new float[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(float), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_float(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), fdata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(fdata, shape));

            case TypeCode.Int64:
                long[] ldata = new long[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(long), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_longlong(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), ldata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(ldata, shape));

            case TypeCode.UInt64:
                ulong[] uldata = new ulong[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(ulong), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_ulonglong(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), uldata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(uldata, shape));


            case TypeCode.Int32:
                int[] idata = new int[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(int), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_int(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), idata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(idata, shape));

            case TypeCode.UInt32:
                uint[] uidata = new uint[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(uint), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_uint(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), uidata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(uidata, shape));

            case TypeCode.Int16:
                short[] sdata = new short[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(short), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_short(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), sdata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(sdata, shape));

            case TypeCode.UInt16:
                ushort[] usdata = new ushort[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(ushort), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_ushort(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), usdata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(usdata, shape));


            case TypeCode.Byte:
                byte[] bdata = new byte[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(byte), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_ubyte(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), bdata);
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(bdata, shape));

            case TypeCode.SByte:
                SByte[] cdata = new SByte[n];
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(SByte), Rank == 0 ? new int[1] : new int[Rank]));
                }
                res = NetCDF.nc_get_vars_schar(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), cdata);
                if (res == -56)
                {
                    res = NetCDF.nc_get_vars_text(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), cdata);
                }
                NetCDFDataSet.HandleResult(res);
                return(ToMultidimArray(cdata, shape));

            case TypeCode.String:
                if (n == 0)
                {
                    return(Array.CreateInstance(typeof(string), Rank == 0 ? new int[1] : new int[Rank]));
                }
                IntPtr[] strdata = new IntPtr[n];
                res = NetCDF.nc_get_vars_string(NcId, varid, ConvertToIntPtr(origin), ConvertToIntPtr(shape), ConvertToIntPtr(stride), strdata);
                NetCDFDataSet.HandleResult(res);

                string[] strings = new string[n];
                for (int i = 0; i < n; i++)
                {
                    strings[i] = UTF8Marshal.PtrToStringUTF8(strdata[i]);                            //Marshal.PtrToStringAnsi(strdata[i]);
                    res        = NetCDF.nc_free_string(new IntPtr(1), new IntPtr[] { strdata[i] });
                    NetCDFDataSet.HandleResult(res);
                }

                // TODO: the memory must be freed?
                //res = NetCDF.nc_free_string(1, strdata);
                //NetCDFDataSet.HandleResult(res);

                return(ToMultidimArray(strings, shape));

            default:
                throw new NotSupportedException("Unsupported type of data.");
            }
        }