Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

New type definition in C#

Tags:

c#

types

I am looking for possibilities to define a new type and using it in C# like below:

Class definition:

public class Position
{
    public double180 Longitude { get; set; } // double180 is a type within a range -180 and 180
    public double90 Latitude { get; set; } // double90 is a type within a range of -90 and 90
}

Usage:

var position = new Position
{
     Longitude = 45,
     Latitude = 96 // This line should give an error while initializing the object
};
like image 664
mnyarar Avatar asked Feb 05 '14 17:02

mnyarar


5 Answers

You don't necessarily need a new type for this. Instead of using an auto property, you can manually write a setter which validates the value:

public double Latitude
{
    get
    {
        return mLatitude;
    }

    set
    {
        if (value > 90 || value < -90)
        {
            throw new ArgumentOutOfRangeException("Invalid latitude");
        }

        mLatitude = value;
    }
}

private double mLatitude;

If you want to reuse this code, you could define your own type and use the above setter in it; then provide an appropriate constructor and conversion operators.

like image 51
TypeIA Avatar answered Oct 17 '22 14:10

TypeIA


A type may be overkill, but if you want one, this is a good start:

struct Double180 : IEquatable<Double180>
{
    private readonly double value;

    public Double180(double d)
    {
        if (d < -180 || d > 180)
        {
            throw new ArgumentOutOfRangeException("d");
        }

        this.value = d;
    }

    public static implicit operator double(Double180 d)
    {
        return d.value;
    }

    public static explicit operator Double180(double d)
    {
        return new Double180(d);
    }

    public override string ToString()
    {
        return this.value.ToString();
    }

    public bool Equals(Double180 other)
    {
        return this.value == other.value;
    }

    public override bool Equals(object obj)
    {
        return obj is Double180 && this.Equals((Double180)obj);
    }

    public override int GetHashCode()
    {
        return this.value.GetHashCode();
    }

    public static bool operator ==(Double180 a, Double180 b)
    {
        return a.Equals(b);
    }

    public static bool operator !=(Double180 a, Double180 b)
    {
        return !a.Equals(b);
    }
}

Of course, there are many more interfaces to implement, for example IConvertible and IComparable<Double180> would be nice.

As you can see, you know where this starts, but you don't know where it ends.

A setter validator, as suggested by the other answers, might be a better idea.

like image 44
Kris Vandermotten Avatar answered Oct 17 '22 16:10

Kris Vandermotten


You would probably be better adding System.ComponentModel.DataAnnotations and using [Range] like so:

public class Position
{
    [Range(-180, 180)]
    public double Longitude { get; set; }

    [Range(-90, 90)]
    public double Latitude { get; set; }
}
like image 21
FrankO Avatar answered Oct 17 '22 14:10

FrankO


Use a double and have the setter check the value:

private double _longitude;
public double Longitude
{
    get
    {
        return _longitude;
    }
    set
    {
        if(value < -180 || value > 180)
        {
            throw new ArgumentException("value");
        }
        _longitude = value;
    }
}
like image 5
Dave Zych Avatar answered Oct 17 '22 16:10

Dave Zych


Add a validation step to the setter:

private double m_Latitude;

public double Latitude
{
  get{return m_Latitude;}

  set
  {
    if(value < -90 || value > 90) throw new ArgumentException("value");

    m_Latitude = value;
  }
}

Note that you as you are providing an implementation of the property you will need to add a member variable to store the underlying property value.

like image 4
Sean Avatar answered Oct 17 '22 16:10

Sean