X, Y, Z Coordinate Struct for .NET PBBGs

I created a struct in C# for storing the X, Y and Z coordinates for characters, objects and rooms within my current PBBG project Perenthia. The struct, called Vector, is serializable and can be used as the key value in a sorted or generic dictionary. Here is the code for the class.

[Serializable]    public struct Vector : IEquatable<Vector>    {        public static readonly Vector Empty = new Vector(0, 0, 0);        public Vector(int x, int y, int z)        {            _x = x;            _y = y;            _z = z;        }        public void SetLocation(int x, int y)        {            this.SetLocation(x, y, this.Z);        }        public void SetLocation(int x, int y, int z)        {            _x = x;            _y = y;            _z = z;        }        public Vector Copy()        {            return new Vector(this.X, this.Y, this.Z);        }        public static Vector FromString(string value)        {            if (!String.IsNullOrEmpty(value))            {                string[] parts = value.Split(',');                if (parts != null && parts.Length == 3)                {                    int x, y, z;                    if (Int32.TryParse(parts[0], out x))                    {                        if (Int32.TryParse(parts[1], out y))                        {                            if (Int32.TryParse(parts[2], out z))                            {                                return new Vector(x, y, z);                            }                        }                    }                }            }            return Vector.Empty;        }        #region GetHashCode        public override int GetHashCode()        {            // The Y value should always come first in any kind of sorting, comparison or hashing operations            // followed by X and then Z because typical loops would start with the Y value.            return (this.Y.GetHashCode() + this.X.GetHashCode() + this.Z.GetHashCode());        }        #endregion        #region Equals        public bool Equals(Vector obj)        {            // The Y value should always come first in any kind of sorting, comparison or hashing operations            // followed by X and then Z because typical loops would start with the Y value.            if (obj != null)            {                if (obj.Y == this.Y)                {                    if (obj.X == this.X)                    {                        return (obj.Z == this.Z);                    }                }            }            return false;        }        public override bool Equals(object obj)        {            if (obj is Vector)            {                return this.Equals((Vector)obj);            }            return base.Equals(obj);        }        #endregion        #region ToString        public override string ToString()        {            return String.Format("{0},{1},{2}", _x, _y, _z);        }        public string ToString(bool forDisplay)        {            if (forDisplay)            {                return String.Format("X = {0}, Y = {1}, Z = {2}", _x, _y, _z);            }            return this.ToString();        }        #endregion        #region Operators        public static Vector operator +(Vector v1, Vector v2)        {            return new Vector(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);        }        public static Vector operator -(Vector v1, Vector v2)        {            return new Vector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);        }        public static bool operator ==(Vector v1, Vector v2)        {            return v1.Equals(v2);        }        public static bool operator !=(Vector v1, Vector v2)        {            return (!v1.Equals(v2));        }        public static bool operator >=(Vector v1, Vector v2)        {            // The Y value should always come first in any kind of sorting, comparison or hashing operations            // followed by X and then Z because typical loops would start with the Y value.            if (v1.Y >= v2.Y)            {                if (v1.X >= v2.X)                {                    return (v1.Z >= v2.Z);                }            }            return false;        }        public static bool operator <=(Vector v1, Vector v2)        {            // The Y value should always come first in any kind of sorting, comparison or hashing operations            // followed by X and then Z because typical loops would start with the Y value.            if (v1.Y <= v2.Y)            {                if (v1.X <= v2.X)                {                    return (v1.Z <= v2.Z);                }            }            return false;        }        #endregion        #region Properties        private int _x;        public int X        {            get { return _x; }            set { _x = value; }        }        private int _y;        public int Y        {            get { return _y; }            set { _y = value; }        }        private int _z;        public int Z        {            get { return _z; }            set { _z = value; }        }        #endregion        #region IEquatable<Vector> Members        bool IEquatable<Vector>.Equals(Vector other)        {            return this.Equals(other);        }        #endregion    }

7/16/2007