我应该使用结构体还是类来表示纬度/经度坐标? [英] Should I use a struct or a class to represent a Lat/Lng coordinate?

查看:30
本文介绍了我应该使用结构体还是类来表示纬度/经度坐标?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用地理编码 API,需要将返回点的坐标表示为纬度/经度对.但是,我不确定是否为此使用结构或类.我最初的想法是使用结构体,但它们似乎在 C# 中普遍不受欢迎(例如,Jon Skeet 提到 在这个答案中,我几乎从不定义自定义结构").性能和内存使用率不是应用程序中的关键因素.

I am working a with a geo-coding API and need to represent the coordinate of a returned point as a Latitude / Longitude pair. However, I am unsure whether to use a struct or a class for this. My initial thought was to use a struct, but they seem to be generally frowned upon in C# (for instance, Jon Skeet mentions in this answer that, "I almost never define custom structs"). Performance and memory usage are not critical factors in the application.

到目前为止,我已经基于一个简单的接口提出了这两个实现:

So far I have come up with these two implementations based on a simple interface:

界面

public interface ILatLng
{
    double Lat { get; }
    double Lng { get; }
}

LatLng 类实现

public class CLatLng : ILatLng
{
    public double Lat { get; private set; }
    public double Lng { get; private set; }

    public CLatLng(double lat, double lng)
    {
        this.Lat = lat;
        this.Lng = lng;
    }

    public override string ToString()
    {
        return String.Format("{0},{1}", this.Lat, this.Lng);
    }

    public override bool Equals(Object obj)
    {
        if (obj == null)
            return false;

        CLatLng latlng = obj as CLatLng;
        if ((Object)latlng == null)
            return false;

        return (this.Lat == latlng.Lat) && (this.Lng == latlng.Lng);
    }

    public bool Equals(CLatLng latlng)
    {
        if ((object)latlng == null)
            return false;

        return (this.Lat == latlng.Lat) && (this.Lng == latlng.Lng);
    }


    public override int GetHashCode()
    {
        return (int)Math.Sqrt(Math.Pow(this.Lat, 2) * Math.Pow(this.Lng, 2));
    }
}

LatLng 结构实现

public struct SLatLng : ILatLng
{
    private double _lat;
    private double _lng;

    public double Lat
    {
        get { return _lat; }
        set { _lat = value; }
    }

    public double Lng
    {
        get { return _lng; }
        set { _lng = value; }
    }

    public SLatLng(double lat, double lng)
    {
        this._lat = lat;
        this._lng = lng;
    }

    public override string ToString()
    {
        return String.Format("{0},{1}", this.Lat, this.Lng);
    }
}

进行一些测试后,我得出以下结论:

Performing some tests I've come to the following findings:

    结构体(作为值类型)永远不能为空,因此将始终包含一个值.但是如果实现一个接口,你仍然可以做这样的事情:

    A struct (being a value type) can never be null, so will always contain a value. But you can still do stuff like this if implementing an interface:

    ILatLng s = new SLatLng();s = null;

    那么在这种情况下结构体使用接口有意义吗?

    So does it make sense for a struct to use an interface in this case?

    • 如果我使用结构体,我是否需要覆盖 EqualsGetHashCode() 等?我的测试表明比较可以在不这样做的情况下正常工作(与类不同) - 所以有必要吗?

    • If I use a struct do I need to override Equals, GetHashCode() etc. ? My tests indicate comparisons work correctly without doing so (unlike with a class) - so is it necessary?

    我觉得使用类更舒服",所以最好坚持使用它们,因为我更了解它们的行为方式吗?使用我的代码的人是否会对值类型语义感到困惑,尤其是在处理接口时?

    I feel more 'comfortable' using classes, so is it best to just stick with them as I'm more aware of how they behave? Will people using my code be confused by value-type semantics, especially when working to an interface?

    CLatLng 实现中,GetHashCode() 的覆盖看起来没问题吗?我从这篇文章中偷"了它,所以我不确定!

    In the CLatLng implementation, does the override of GetHashCode() seem OK? I 'stole' it from this article, so am unsure!

    感谢收到任何帮助或建议!

    Any help or advice gratefully received!

    推荐答案

    老实说,我看不出为此提供一个界面有任何意义.

    I can't see any point in having an interface for this, to be honest.

    我只想创建一个结构体,但使其不可变 - 可变结构体是一个非常糟糕的主意.我还会使用完整的 LatitudeLongitude 作为属性名称.像这样:

    I would just create a struct, but make it immutable - mutable structs are a really bad idea. I'd also use full Latitude and Longitude as the property names. Something like this:

    public struct GeoCoordinate
    {
        private readonly double latitude;
        private readonly double longitude;
    
        public double Latitude { get { return latitude; } }
        public double Longitude { get { return longitude; } }
    
        public GeoCoordinate(double latitude, double longitude)
        {
            this.latitude = latitude;
            this.longitude = longitude;
        }
    
        public override string ToString()
        {
            return string.Format("{0},{1}", Latitude, Longitude);
        }
    }
    

    然后我会实现IEquatable并覆盖EqualsGetHashCode,例如

    I'd then also implement IEquatable<GeoCoordinate> and override Equals and GetHashCode, e.g.

    public override bool Equals(Object other)
    {
        return other is GeoCoordinate && Equals((GeoCoordinate) other);
    }
    
    public bool Equals(GeoCoordinate other)
    {
        return Latitude == other.Latitude && Longitude == other.Longitude;
    }
    
    public override int GetHashCode()
    {
        return Latitude.GetHashCode() ^ Longitude.GetHashCode();
    }
    

    请注意,您需要了解对双打进行相等比较的正常危险 - 这里没有太多选择,但是两个看起来应该相等的可能并不......

    Note that you need to be aware of the normal dangers of performing equality comparisons on doubles - there's not much alternative here, but two values which look like they should be equal may not be...

    关于无参数构造函数的观点是合理的,但我怀疑你会发现它实际上不会咬你.

    The point about the parameterless constructor is a reasonable one, but I suspect you'll find it won't actually bite you.

    这篇关于我应该使用结构体还是类来表示纬度/经度坐标?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆