NewLife/NewLife.Map

优化GeoPoint,本想使用readonly struct,但不知道如何区分无效坐标。
智能大石头 编写于 2024-04-29 00:19:47
共计: 修改19个文件,增加169行、删除186行。
修改 +4 -4
修改 +3 -3
修改 +3 -3
修改 +3 -3
修改 +1 -1
修改 +14 -21
修改 +29 -41
修改 +13 -13
修改 +4 -4
修改 +13 -4
修改 +10 -8
修改 +7 -7
修改 +5 -5
修改 +27 -31
修改 +13 -12
修改 +3 -4
修改 +6 -8
修改 +8 -10
修改 +3 -4
修改 +4 -4
diff --git "a/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2566\344\275\215.Biz.cs" "b/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2566\344\275\215.Biz.cs"
index 97d9b0d..4677df4 100644
--- "a/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2566\344\275\215.Biz.cs"
+++ "b/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2566\344\275\215.Biz.cs"
@@ -1,4 +1,4 @@
-using NewLife;
+using NewLife;
 using NewLife.Data;
 using XCode;
 using XCode.Membership;
@@ -146,7 +146,7 @@ public partial class Geo6 : Entity<Geo6>, IGeo
     /// <returns>实体列表</returns>
     public static IList<Geo6> FindAllByHash(String hash)
     {
-        if (hash.IsNullOrEmpty()) return new List<Geo6>();
+        if (hash.IsNullOrEmpty()) return [];
 
         // 实体缓存
         if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.Hash.EqualIgnoreCase(hash));
@@ -159,7 +159,7 @@ public partial class Geo6 : Entity<Geo6>, IGeo
     /// <returns>实体列表</returns>
     public static IList<Geo6> FindAllByHashBd09(String hashBd09)
     {
-        if (hashBd09.IsNullOrEmpty()) return new List<Geo6>();
+        if (hashBd09.IsNullOrEmpty()) return [];
 
         // 实体缓存
         if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.HashBd09.EqualIgnoreCase(hashBd09));
@@ -172,7 +172,7 @@ public partial class Geo6 : Entity<Geo6>, IGeo
     /// <returns>实体列表</returns>
     public static IList<Geo6> FindAllByHashGcj02(String hashGcj02)
     {
-        if (hashGcj02.IsNullOrEmpty()) return new List<Geo6>();
+        if (hashGcj02.IsNullOrEmpty()) return [];
 
         // 实体缓存
         if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.HashGcj02.EqualIgnoreCase(hashGcj02));
修改 +3 -3
diff --git "a/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2567\344\275\215.Biz.cs" "b/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2567\344\275\215.Biz.cs"
index 05c08b4..b539d33 100644
--- "a/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2567\344\275\215.Biz.cs"
+++ "b/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2567\344\275\215.Biz.cs"
@@ -143,7 +143,7 @@ public partial class Geo7 : Entity<Geo7>, IGeo
     /// <returns>实体列表</returns>
     public static IList<Geo7> FindAllByHash(String hash)
     {
-        if (hash.IsNullOrEmpty()) return new List<Geo7>();
+        if (hash.IsNullOrEmpty()) return [];
 
         // 实体缓存
         if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.Hash.EqualIgnoreCase(hash));
@@ -156,7 +156,7 @@ public partial class Geo7 : Entity<Geo7>, IGeo
     /// <returns>实体列表</returns>
     public static IList<Geo7> FindAllByHashBd09(String hashBd09)
     {
-        if (hashBd09.IsNullOrEmpty()) return new List<Geo7>();
+        if (hashBd09.IsNullOrEmpty()) return [];
 
         // 实体缓存
         if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.HashBd09.EqualIgnoreCase(hashBd09));
@@ -169,7 +169,7 @@ public partial class Geo7 : Entity<Geo7>, IGeo
     /// <returns>实体列表</returns>
     public static IList<Geo7> FindAllByHashGcj02(String hashGcj02)
     {
-        if (hashGcj02.IsNullOrEmpty()) return new List<Geo7>();
+        if (hashGcj02.IsNullOrEmpty()) return [];
 
         // 实体缓存
         if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.HashGcj02.EqualIgnoreCase(hashGcj02));
修改 +3 -3
diff --git "a/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2568\344\275\215.Biz.cs" "b/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2568\344\275\215.Biz.cs"
index 005d94e..96c4465 100644
--- "a/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2568\344\275\215.Biz.cs"
+++ "b/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2568\344\275\215.Biz.cs"
@@ -143,7 +143,7 @@ public partial class Geo8 : Entity<Geo8>, IGeo
     /// <returns>实体列表</returns>
     public static IList<Geo8> FindAllByHash(String hash)
     {
-        if (hash.IsNullOrEmpty()) return new List<Geo8>();
+        if (hash.IsNullOrEmpty()) return [];
 
         // 实体缓存
         if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.Hash.EqualIgnoreCase(hash));
@@ -156,7 +156,7 @@ public partial class Geo8 : Entity<Geo8>, IGeo
     /// <returns>实体列表</returns>
     public static IList<Geo8> FindAllByHashBd09(String hashBd09)
     {
-        if (hashBd09.IsNullOrEmpty()) return new List<Geo8>();
+        if (hashBd09.IsNullOrEmpty()) return [];
 
         // 实体缓存
         if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.HashBd09.EqualIgnoreCase(hashBd09));
@@ -169,7 +169,7 @@ public partial class Geo8 : Entity<Geo8>, IGeo
     /// <returns>实体列表</returns>
     public static IList<Geo8> FindAllByHashGcj02(String hashGcj02)
     {
-        if (hashGcj02.IsNullOrEmpty()) return new List<Geo8>();
+        if (hashGcj02.IsNullOrEmpty()) return [];
 
         // 实体缓存
         if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.HashGcj02.EqualIgnoreCase(hashGcj02));
修改 +3 -3
diff --git "a/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2569\344\275\215.Biz.cs" "b/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2569\344\275\215.Biz.cs"
index 1791fe3..5f04998 100644
--- "a/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2569\344\275\215.Biz.cs"
+++ "b/MapApi/Locations/\345\234\260\347\220\206\346\225\260\346\215\2569\344\275\215.Biz.cs"
@@ -143,7 +143,7 @@ public partial class Geo9 : Entity<Geo9>, IGeo
     /// <returns>实体列表</returns>
     public static IList<Geo9> FindAllByHash(String hash)
     {
-        if (hash.IsNullOrEmpty()) return new List<Geo9>();
+        if (hash.IsNullOrEmpty()) return [];
 
         // 实体缓存
         if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.Hash.EqualIgnoreCase(hash));
@@ -156,7 +156,7 @@ public partial class Geo9 : Entity<Geo9>, IGeo
     /// <returns>实体列表</returns>
     public static IList<Geo9> FindAllByHashBd09(String hashBd09)
     {
-        if (hashBd09.IsNullOrEmpty()) return new List<Geo9>();
+        if (hashBd09.IsNullOrEmpty()) return [];
 
         // 实体缓存
         if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.HashBd09.EqualIgnoreCase(hashBd09));
@@ -169,7 +169,7 @@ public partial class Geo9 : Entity<Geo9>, IGeo
     /// <returns>实体列表</returns>
     public static IList<Geo9> FindAllByHashGcj02(String hashGcj02)
     {
-        if (hashGcj02.IsNullOrEmpty()) return new List<Geo9>();
+        if (hashGcj02.IsNullOrEmpty()) return [];
 
         // 实体缓存
         if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.HashGcj02.EqualIgnoreCase(hashGcj02));
修改 +1 -1
diff --git "a/MapApi/Locations/\345\234\260\345\233\276\346\217\220\344\276\233\350\200\205.Biz.cs" "b/MapApi/Locations/\345\234\260\345\233\276\346\217\220\344\276\233\350\200\205.Biz.cs"
index 53336cc..8931a51 100644
--- "a/MapApi/Locations/\345\234\260\345\233\276\346\217\220\344\276\233\350\200\205.Biz.cs"
+++ "b/MapApi/Locations/\345\234\260\345\233\276\346\217\220\344\276\233\350\200\205.Biz.cs"
@@ -122,7 +122,7 @@ public partial class MapProvider : Entity<MapProvider>
     /// <returns>实体列表</returns>
     public static IList<MapProvider> FindAllByKind(NewLife.Map.Models.MapKinds kind)
     {
-        if (kind <= 0) return new List<MapProvider>();
+        if (kind <= 0) return [];
 
         // 实体缓存
         if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.Kind == kind);
修改 +14 -21
diff --git a/NewLife.Map/AMap.cs b/NewLife.Map/AMap.cs
index 66f5475..8a98fba 100644
--- a/NewLife.Map/AMap.cs
+++ b/NewLife.Map/AMap.cs
@@ -43,7 +43,7 @@ public class AMap : Map, IMap
     /// <param name="url">目标Url</param>
     /// <param name="result">结果字段</param>
     /// <returns></returns>
-    protected override async Task<T> InvokeAsync<T>(String url, String result)
+    protected override async Task<T> InvokeAsync<T>(String url, String? result)
     {
         var dic = await base.InvokeAsync<IDictionary<String, Object>>(url, result);
         if (dic == null || dic.Count == 0) return default;
@@ -54,7 +54,7 @@ public class AMap : Map, IMap
             var msg = dic["info"] + "";
 
             // 删除无效密钥
-            if (IsValidKey(msg)) RemoveKey(LastKey, DateTime.Now.AddHours(1));
+            if (!LastKey.IsNullOrEmpty() && IsValidKey(msg)) RemoveKey(LastKey, DateTime.Now.AddHours(1));
 
             return !ThrowException ? default : throw new Exception(msg);
         }
@@ -71,7 +71,7 @@ public class AMap : Map, IMap
     /// <param name="city"></param>
     /// <param name="coordtype"></param>
     /// <returns></returns>
-    protected async Task<IDictionary<String, Object>> GetGeocoderAsync(String address, String city = null, String coordtype = null)
+    protected async Task<IDictionary<String, Object>?> GetGeocoderAsync(String address, String? city = null, String? coordtype = null)
     {
         if (address.IsNullOrEmpty()) throw new ArgumentNullException(nameof(address));
 
@@ -91,21 +91,16 @@ public class AMap : Map, IMap
     /// <param name="coordtype"></param>
     /// <param name="formatAddress">是否格式化地址。高德地图默认已经格式化地址</param>
     /// <returns></returns>
-    public async Task<GeoAddress> GetGeoAsync(String address, String city = null, String coordtype = null, Boolean formatAddress = false)
+    public async Task<GeoAddress?> GetGeoAsync(String address, String? city = null, String? coordtype = null, Boolean formatAddress = false)
     {
         var rs = await GetGeocoderAsync(address, city);
         if (rs == null || rs.Count == 0) return null;
 
-        var gp = new GeoPoint();
-
-        var ds = (rs["location"] + "").Split(',');
-        if (ds != null && ds.Length >= 2)
+        var geo = new GeoAddress
         {
-            gp.Longitude = ds[0].ToDouble();
-            gp.Latitude = ds[1].ToDouble();
-        }
+            Location = new(rs["location"] as String)
+        };
 
-        var geo = new GeoAddress();
         var reader = new JsonReader();
         reader.ToObject(rs, null, geo);
 
@@ -114,11 +109,9 @@ public class AMap : Map, IMap
         if (rs["township"] is IList<Object> ts && ts.Count > 0) geo.Township = ts[0] + "";
         if (rs["number"] is IList<Object> ns && ns.Count > 0) geo.StreetNumber = ns[0] + "";
 
-        geo.Location = gp;
-
         if (formatAddress)
         {
-            var geo2 = await GetReverseGeoAsync(gp, "wcj02");
+            var geo2 = await GetReverseGeoAsync(geo.Location, "wcj02");
             if (geo2 != null)
             {
                 geo = geo2;
@@ -153,7 +146,7 @@ public class AMap : Map, IMap
     /// <param name="point"></param>
     /// <param name="coordtype"></param>
     /// <returns></returns>
-    protected async Task<IDictionary<String, Object>> GetReverseGeocoderAsync(GeoPoint point, String coordtype)
+    protected async Task<IDictionary<String, Object>> GetReverseGeocoderAsync(GeoPoint point, String? coordtype)
     {
         if (point.Longitude < 0.1 || point.Latitude < 0.1) throw new ArgumentNullException(nameof(point));
 
@@ -166,7 +159,7 @@ public class AMap : Map, IMap
     /// <param name="point"></param>
     /// <param name="coordtype">坐标系</param>
     /// <returns></returns>
-    public async Task<GeoAddress> GetReverseGeoAsync(GeoPoint point, String coordtype)
+    public async Task<GeoAddress?> GetReverseGeoAsync(GeoPoint point, String? coordtype)
     {
         var rs = await GetReverseGeocoderAsync(point, coordtype);
         if (rs == null || rs.Count == 0) return null;
@@ -243,7 +236,7 @@ public class AMap : Map, IMap
     /// <param name="coordtype"></param>
     /// <param name="type">路径计算的方式和方法</param>
     /// <returns></returns>
-    public async Task<Driving> GetDistanceAsync(GeoPoint origin, GeoPoint destination, String coordtype, Int32 type = 1)
+    public async Task<Driving?> GetDistanceAsync(GeoPoint origin, GeoPoint destination, String? coordtype, Int32 type = 1)
     {
         if (origin == null || origin.Longitude < 1 && origin.Latitude < 1) throw new ArgumentNullException(nameof(origin));
         if (destination == null || destination.Longitude < 1 && destination.Latitude < 1) throw new ArgumentNullException(nameof(destination));
@@ -285,9 +278,9 @@ public class AMap : Map, IMap
         var url = $"http://restapi.amap.com/v3/config/district?keywords={keywords}&subdistrict={subdistrict}&filter={code}&extensions=base&output=json";
 
         var list = await InvokeAsync<IList<Object>>(url, "districts");
-        if (list == null || list.Count == 0) return null;
+        if (list == null || list.Count == 0) return [];
 
-        if (list.FirstOrDefault() is not IDictionary<String, Object> geo) return null;
+        if (list.FirstOrDefault() is not IDictionary<String, Object> geo) return [];
 
         var addrs = GetArea(geo, 0);
 
@@ -296,7 +289,7 @@ public class AMap : Map, IMap
 
     private IList<GeoArea> GetArea(IDictionary<String, Object> geo, Int32 parentCode)
     {
-        if (geo == null || geo.Count == 0) return null;
+        if (geo == null || geo.Count == 0) return [];
 
         var addrs = new List<GeoArea>();
 
修改 +29 -41
diff --git a/NewLife.Map/BaiduMap.cs b/NewLife.Map/BaiduMap.cs
index 91e4a98..5e46361 100644
--- a/NewLife.Map/BaiduMap.cs
+++ b/NewLife.Map/BaiduMap.cs
@@ -30,7 +30,7 @@ public class BaiduMap : Map, IMap
     /// <param name="url">目标Url</param>
     /// <param name="result">结果字段</param>
     /// <returns></returns>
-    protected override async Task<T> InvokeAsync<T>(String url, String result)
+    protected override async Task<T> InvokeAsync<T>(String url, String? result)
     {
         var dic = await base.InvokeAsync<IDictionary<String, Object>>(url, result);
         if (dic == null || dic.Count == 0) return default;
@@ -61,7 +61,7 @@ public class BaiduMap : Map, IMap
     /// <param name="city"></param>
     /// <param name="coordtype"></param>
     /// <returns></returns>
-    protected async Task<IDictionary<String, Object>> GetGeocoderAsync(String address, String city = null, String coordtype = null)
+    protected async Task<IDictionary<String, Object>> GetGeocoderAsync(String address, String? city = null, String? coordtype = null)
     {
         if (address.IsNullOrEmpty()) throw new ArgumentNullException(nameof(address));
 
@@ -80,25 +80,23 @@ public class BaiduMap : Map, IMap
     /// <param name="coordtype"></param>
     /// <param name="formatAddress">是否格式化地址</param>
     /// <returns></returns>
-    public async Task<GeoAddress> GetGeoAsync(String address, String city = null, String coordtype = null, Boolean formatAddress = false)
+    public async Task<GeoAddress?> GetGeoAsync(String address, String? city = null, String? coordtype = null, Boolean formatAddress = false)
     {
         var rs = await GetGeocoderAsync(address, city, coordtype);
         if (rs == null || rs.Count == 0) return null;
 
         if (rs["location"] is not IDictionary<String, Object> ds || ds.Count < 2) return null;
 
-        var gp = new GeoPoint
-        {
-            Longitude = ds["lng"].ToDouble(),
-            Latitude = ds["lat"].ToDouble()
-        };
-
         var geo = new GeoAddress
         {
-            Location = gp,
+            Location = new(ds["lng"], ds["lat"]),
         };
 
-        if (formatAddress && gp != null) geo = await GetReverseGeoAsync(gp, coordtype);
+        if (formatAddress)
+        {
+            var geo2 = await GetReverseGeoAsync(geo.Location, coordtype);
+            if (geo2 != null) geo = geo2;
+        }
 
         geo.Precise = rs["precise"].ToBoolean();
         geo.Confidence = rs["confidence"].ToInt();
@@ -117,7 +115,7 @@ public class BaiduMap : Map, IMap
     /// <param name="point"></param>
     /// <param name="coordtype">坐标系</param>
     /// <returns></returns>
-    protected async Task<IDictionary<String, Object>> GetReverseGeocoderAsync(GeoPoint point, String coordtype)
+    protected async Task<IDictionary<String, Object>> GetReverseGeocoderAsync(GeoPoint point, String? coordtype)
     {
         if (point == null || point.Longitude == 0 || point.Latitude == 0) throw new ArgumentNullException(nameof(point));
 
@@ -130,7 +128,7 @@ public class BaiduMap : Map, IMap
     /// <param name="point"></param>
     /// <param name="coordtype"></param>
     /// <returns></returns>
-    public async Task<GeoAddress> GetReverseGeoAsync(GeoPoint point, String coordtype)
+    public async Task<GeoAddress?> GetReverseGeoAsync(GeoPoint point, String? coordtype)
     {
         var rs = await GetReverseGeocoderAsync(point, coordtype);
         if (rs == null || rs.Count == 0) return null;
@@ -142,11 +140,7 @@ public class BaiduMap : Map, IMap
         };
         if (rs["location"] is IDictionary<String, Object> ds && ds.Count >= 2)
         {
-            addr.Location = new GeoPoint
-            {
-                Longitude = ds["lng"].ToDouble(),
-                Latitude = ds["lat"].ToDouble()
-            };
+            addr.Location = new(ds["lng"], ds["lat"]);
         }
 
         if (rs["addressComponent"] is IDictionary<String, Object> component)
@@ -178,7 +172,7 @@ public class BaiduMap : Map, IMap
     /// <param name="coordtype"></param>
     /// <param name="type">路径计算的方式和方法</param>
     /// <returns></returns>
-    public async Task<Driving> GetDistanceAsync(GeoPoint origin, GeoPoint destination, String coordtype, Int32 type = 13)
+    public async Task<Driving?> GetDistanceAsync(GeoPoint origin, GeoPoint destination, String? coordtype, Int32 type = 13)
     {
         if (origin == null || origin.Longitude < 1 && origin.Latitude < 1) throw new ArgumentNullException(nameof(origin));
         if (destination == null || destination.Longitude < 1 && destination.Latitude < 1) throw new ArgumentNullException(nameof(destination));
@@ -198,8 +192,8 @@ public class BaiduMap : Map, IMap
 
         var rs = new Driving
         {
-            Distance = d1["value"].ToInt(),
-            Duration = d2["value"].ToInt()
+            Distance = d1?["value"].ToInt() ?? 0,
+            Duration = d2?["value"].ToInt() ?? 0
         };
 
         return rs;
@@ -217,7 +211,7 @@ public class BaiduMap : Map, IMap
     /// <param name="coordtype"></param>
     /// <param name="formatAddress"></param>
     /// <returns></returns>
-    public async Task<GeoAddress> PlaceSearchAsync(String query, String tag, String region, String coordtype = null, Boolean formatAddress = true)
+    public async Task<GeoAddress?> PlaceSearchAsync(String query, String tag, String region, String? coordtype = null, Boolean formatAddress = true)
     {
         // 编码
         query = HttpUtility.UrlEncode(query);
@@ -235,13 +229,7 @@ public class BaiduMap : Map, IMap
 
         if (rs["location"] is IDictionary<String, Object> ds && ds.Count >= 2)
         {
-            var point = new GeoPoint
-            {
-                Longitude = ds["lng"].ToDouble(),
-                Latitude = ds["lat"].ToDouble()
-            };
-
-            geo.Location = point;
+            geo.Location = new(ds["lng"], ds["lat"]);
         }
         //else if (rs["num"] is Int32 num && num > 0 && rs["name"] != null)
         //{
@@ -251,7 +239,11 @@ public class BaiduMap : Map, IMap
         else
             return null;
 
-        if (formatAddress && geo?.Location != null) geo = await GetReverseGeoAsync(geo.Location, coordtype);
+        if (formatAddress && geo.Location != null)
+        {
+            var geo2 = await GetReverseGeoAsync(geo.Location, coordtype);
+            if (geo2 != null) geo = geo2;
+        }
 
         geo.Name = rs["name"] + "";
         var addr = rs["address"] + "";
@@ -269,24 +261,24 @@ public class BaiduMap : Map, IMap
     /// <param name="ip"></param>
     /// <param name="coordtype"></param>
     /// <returns></returns>
-    public async Task<IDictionary<String, Object>> IpLocationAsync(String ip, String coordtype)
+    public async Task<IDictionary<String, Object?>?> IpLocationAsync(String ip, String coordtype)
     {
         var url = $"/location/ip?ip={ip}&coor={coordtype}";
 
         var dic = await InvokeAsync<IDictionary<String, Object>>(url, null);
         if (dic == null || dic.Count == 0) return null;
 
-        if (dic["content"] is not IDictionary<String, Object> rs) return null;
+        if (dic["content"] is not IDictionary<String, Object?> rs) return null;
 
         if (dic.TryGetValue("address", out var fulladdress)) rs["full_address"] = fulladdress;
         if (rs.TryGetValue("address_detail", out var v1))
         {
-            rs.Merge(v1);
+            if (v1 != null) rs.Merge(v1);
             rs.Remove("address_detail");
         }
         if (rs.TryGetValue("point", out var v2))
         {
-            rs.Merge(v2);
+            if (v2 != null) rs.Merge(v2);
             rs.Remove("point");
         }
 
@@ -328,17 +320,13 @@ public class BaiduMap : Map, IMap
 
         var url = $"/geoconv/v1/?coords={points.Join(";", e => $"{e.Longitude},{e.Latitude}")}&from={idxFrom}&to={idxTo}&output=json";
 
+        var list = new List<GeoPoint>();
         var rs = await InvokeAsync<IList<Object>>(url, "result");
-        if (rs == null || rs.Count == 0) return null;
+        if (rs == null || rs.Count == 0) return list;
 
-        var list = new List<GeoPoint>();
         foreach (var item in rs.Cast<IDictionary<String, Object>>())
         {
-            list.Add(new GeoPoint
-            {
-                Longitude = item["x"].ToDouble(),
-                Latitude = item["y"].ToDouble()
-            });
+            list.Add(new(item["x"], item["y"]));
         }
 
         return list;
修改 +13 -13
diff --git a/NewLife.Map/Data/GeoAddress.cs b/NewLife.Map/Data/GeoAddress.cs
index ecb9cc4..3399b8f 100644
--- a/NewLife.Map/Data/GeoAddress.cs
+++ b/NewLife.Map/Data/GeoAddress.cs
@@ -5,46 +5,46 @@ public class GeoAddress
 {
     #region 属性
     /// <summary>名称</summary>
-    public String Name { get; set; }
+    public String? Name { get; set; }
 
     /// <summary>坐标</summary>
-    public GeoPoint Location { get; set; }
+    public GeoPoint? Location { get; set; }
 
     /// <summary>地址</summary>
-    public String Address { get; set; }
+    public String? Address { get; set; }
 
     /// <summary>标题。语义描述,POI详细信息,例如石下村东南282米</summary>
-    public String Title { get; set; }
+    public String? Title { get; set; }
 
     /// <summary>行政区域编码。6位数字</summary>
     public Int32 Code { get; set; }
 
     /// <summary>国家</summary>
-    public String Country { get; set; }
+    public String? Country { get; set; }
 
     /// <summary>省份</summary>
-    public String Province { get; set; }
+    public String? Province { get; set; }
 
     /// <summary>城市</summary>
-    public String City { get; set; }
+    public String? City { get; set; }
 
     /// <summary>区县</summary>
-    public String District { get; set; }
+    public String? District { get; set; }
 
     /// <summary>乡镇</summary>
-    public String Township { get; set; }
+    public String? Township { get; set; }
 
     /// <summary>乡镇编码。9位数字</summary>
     public Int32 Towncode { get; set; }
 
     /// <summary>街道</summary>
-    public String Street { get; set; }
+    public String? Street { get; set; }
 
     /// <summary>街道编码</summary>
-    public String StreetNumber { get; set; }
+    public String? StreetNumber { get; set; }
 
     /// <summary>级别</summary>
-    public String Level { get; set; }
+    public String? Level { get; set; }
 
     /// <summary>精确打点。位置的附加信息,是否精确查找。1为精确查找,即准确打点;0为不精确,即模糊打点。</summary>
     public Boolean Precise { get; set; }
@@ -81,5 +81,5 @@ public class GeoAddress
 
     /// <summary>已重载。</summary>
     /// <returns></returns>
-    public override String ToString() => Address;
+    public override String? ToString() => Address;
 }
\ No newline at end of file
修改 +4 -4
diff --git a/NewLife.Map/Data/GeoArea.cs b/NewLife.Map/Data/GeoArea.cs
index de3e41a..fd5d6fa 100644
--- a/NewLife.Map/Data/GeoArea.cs
+++ b/NewLife.Map/Data/GeoArea.cs
@@ -8,19 +8,19 @@ public class GeoArea
     public Int32 Code { get; set; }
 
     /// <summary>名称</summary>
-    public String Name { get; set; }
+    public String? Name { get; set; }
 
     /// <summary>父级</summary>
     public Int32 ParentCode { get; set; }
 
     /// <summary>中心</summary>
-    public String Center { get; set; }
+    public String? Center { get; set; }
 
     /// <summary>边界</summary>
-    public String Polyline { get; set; }
+    public String? Polyline { get; set; }
 
     /// <summary>级别</summary>
-    public String Level { get; set; }
+    public String? Level { get; set; }
     #endregion
 
     /// <summary>已重载。</summary>
修改 +13 -4
diff --git a/NewLife.Map/Data/GeoPoint.cs b/NewLife.Map/Data/GeoPoint.cs
index f6ab346..ff6d000 100644
--- a/NewLife.Map/Data/GeoPoint.cs
+++ b/NewLife.Map/Data/GeoPoint.cs
@@ -5,10 +5,10 @@ public class GeoPoint
 {
     #region 属性
     /// <summary>经度</summary>
-    public Double Longitude { get; set; }
+    public Double Longitude { get; }
 
     /// <summary>纬度</summary>
-    public Double Latitude { get; set; }
+    public Double Latitude { get; }
     #endregion
 
     #region 构造
@@ -24,9 +24,18 @@ public class GeoPoint
         Latitude = latitude;
     }
 
+    /// <summary>实例化经纬度坐标</summary>
+    /// <param name="longitude"></param>
+    /// <param name="latitude"></param>
+    public GeoPoint(Object longitude, Object latitude)
+    {
+        Longitude = longitude.ToDouble();
+        Latitude = latitude.ToDouble();
+    }
+
     /// <summary>经纬度坐标</summary>
     /// <param name="location"></param>
-    public GeoPoint(String location)
+    public GeoPoint(String? location)
     {
         if (!location.IsNullOrEmpty())
         {
@@ -52,7 +61,7 @@ public class GeoPoint
     public static GeoPoint Decode(String hash)
     {
         var p = GeoHash.Decode(hash);
-        return new GeoPoint(p.Longitude, p.Latitude);
+        return new(p.Longitude, p.Latitude);
     }
     #endregion
 
修改 +10 -8
diff --git a/NewLife.Map/Map.cs b/NewLife.Map/Map.cs
index 8392b12..a45acdd 100644
--- a/NewLife.Map/Map.cs
+++ b/NewLife.Map/Map.cs
@@ -16,7 +16,7 @@ public interface IMap
 {
     #region 属性
     /// <summary>应用密钥。多个key逗号分隔</summary>
-    String AppKey { get; set; }
+    String? AppKey { get; set; }
     #endregion
 
     #region 方法
@@ -33,7 +33,7 @@ public interface IMap
     /// <param name="coordtype">所需要的坐标系</param>
     /// <param name="formatAddress">是否格式化地址</param>
     /// <returns></returns>
-    Task<GeoAddress> GetGeoAsync(String address, String? city = null, String? coordtype = null, Boolean formatAddress = false);
+    Task<GeoAddress?> GetGeoAsync(String address, String? city = null, String? coordtype = null, Boolean formatAddress = false);
     #endregion
 
     #region 逆地理编码
@@ -41,7 +41,7 @@ public interface IMap
     /// <param name="point">坐标</param>
     /// <param name="coordtype">坐标系</param>
     /// <returns></returns>
-    Task<GeoAddress> GetReverseGeoAsync(GeoPoint point, String coordtype);
+    Task<GeoAddress?> GetReverseGeoAsync(GeoPoint point, String? coordtype);
     #endregion
 
     #region 路径规划
@@ -51,7 +51,7 @@ public interface IMap
     /// <param name="coordtype">坐标系</param>
     /// <param name="type">路径计算的方式和方法</param>
     /// <returns></returns>
-    Task<Driving> GetDistanceAsync(GeoPoint origin, GeoPoint destination, String coordtype, Int32 type = 0);
+    Task<Driving?> GetDistanceAsync(GeoPoint origin, GeoPoint destination, String? coordtype, Int32 type = 0);
     #endregion
 
     #region 坐标系转换
@@ -158,7 +158,7 @@ public abstract class Map : DisposeBase
     /// <param name="url">目标Url</param>
     /// <param name="result">结果字段</param>
     /// <returns></returns>
-    protected virtual async Task<T?> InvokeAsync<T>(String url, String result) where T : class
+    protected virtual async Task<T?> InvokeAsync<T>(String url, String? result) where T : class
     {
         LastResult = null;
 
@@ -198,8 +198,10 @@ public abstract class Map : DisposeBase
     /// <summary>移除暂时不可用密钥</summary>
     /// <param name="key"></param>
     /// <param name="reviveTime">复苏时间。达到该时间时,重新启用该key</param>
-    protected void RemoveKey(String key, DateTime reviveTime)
+    protected void RemoveKey(String? key, DateTime reviveTime)
     {
+        if (key.IsNullOrEmpty()) return;
+
         lock (this)
         {
             // 使用本地变量保存数据,避免多线程冲突
@@ -319,7 +321,7 @@ public static class MapHelper
     /// <returns></returns>
     public static async Task<GeoPoint?> ConvertAsync(this IMap map, GeoPoint point, String from, String to)
     {
-        var list = await map.ConvertAsync(new[] { point }, from, to);
-        return list.Count == 0 ? null : list[0];
+        var list = await map.ConvertAsync([point], from, to);
+        return list == null || list.Count == 0 ? null : list[0];
     }
 }
\ No newline at end of file
修改 +7 -7
diff --git a/NewLife.Map/Models/GeoModel.cs b/NewLife.Map/Models/GeoModel.cs
index 4e8d2e4..0327d36 100644
--- a/NewLife.Map/Models/GeoModel.cs
+++ b/NewLife.Map/Models/GeoModel.cs
@@ -7,7 +7,7 @@ public class GeoModel
 {
     #region 属性
     /// <summary>Geo哈希编码。基于wgs84坐标</summary>
-    public String Hash { get; set; }
+    public String? Hash { get; set; }
 
     /// <summary>经度。wgw84坐标</summary>
     public Double Longitude { get; set; }
@@ -16,10 +16,10 @@ public class GeoModel
     public Double Latitude { get; set; }
 
     /// <summary>地址。例如XX高速、XX路</summary>
-    public String Address { get; set; }
+    public String? Address { get; set; }
 
     /// <summary>标题。POI语义地址</summary>
-    public String Title { get; set; }
+    public String? Title { get; set; }
 
     /// <summary>百度经度。bd09坐标</summary>
     public Double LongitudeBd09 { get; set; }
@@ -37,25 +37,25 @@ public class GeoModel
     public Int32 AreaCode { get; set; }
 
     /// <summary>区域名称。乡镇四级地址</summary>
-    public String AreaName { get; set; }
+    public String? AreaName { get; set; }
 
     /// <summary>省份编码</summary>
     public Int32 ProvinceId { get; set; }
 
     /// <summary>省份名称</summary>
-    public String Province { get; set; }
+    public String? Province { get; set; }
 
     /// <summary>城市编码</summary>
     public Int32 CityId { get; set; }
 
     /// <summary>城市名称</summary>
-    public String City { get; set; }
+    public String? City { get; set; }
 
     /// <summary>区县编码</summary>
     public Int32 DistrictId { get; set; }
 
     /// <summary>区县名称</summary>
-    public String District { get; set; }
+    public String? District { get; set; }
     #endregion
 
     #region 方法
修改 +5 -5
diff --git a/NewLife.Map/NewLifeMap.cs b/NewLife.Map/NewLifeMap.cs
index 7a85030..4d23207 100644
--- a/NewLife.Map/NewLifeMap.cs
+++ b/NewLife.Map/NewLifeMap.cs
@@ -63,7 +63,7 @@ public class NewLifeMap : Map, IMap
     #endregion
 
     #region 方法
-    private ApiHttpClient _client;
+    private ApiHttpClient? _client;
     /// <summary>获取通信客户端</summary>
     /// <returns></returns>
     /// <exception cref="Exception"></exception>
@@ -89,7 +89,7 @@ public class NewLifeMap : Map, IMap
     /// <param name="formatAddress"></param>
     /// <returns></returns>
     /// <exception cref="NotImplementedException"></exception>
-    public Task<GeoAddress> GetGeoAsync(String address, String city = null, String coordtype = null, Boolean formatAddress = false) => throw new NotImplementedException();
+    public Task<GeoAddress?> GetGeoAsync(String address, String? city = null, String? coordtype = null, Boolean formatAddress = false) => throw new NotImplementedException();
     #endregion
 
     #region 逆地理编码
@@ -97,7 +97,7 @@ public class NewLifeMap : Map, IMap
     /// <param name="point"></param>
     /// <param name="coordtype"></param>
     /// <returns></returns>
-    public async Task<GeoAddress> GetReverseGeoAsync(GeoPoint point, String coordtype)
+    public async Task<GeoAddress?> GetReverseGeoAsync(GeoPoint point, String? coordtype)
     {
         var rs = await GetGeoInfo(point, coordtype);
         if (rs == null) return null;
@@ -109,7 +109,7 @@ public class NewLifeMap : Map, IMap
     /// <param name="point"></param>
     /// <param name="coordtype"></param>
     /// <returns></returns>
-    public async Task<GeoModel> GetGeoInfo(GeoPoint point, String coordtype)
+    public async Task<GeoModel?> GetGeoInfo(GeoPoint point, String? coordtype)
     {
         return await GetClient().GetAsync<GeoModel>("/Map/ReverseGeo", new
         {
@@ -130,6 +130,6 @@ public class NewLifeMap : Map, IMap
     /// <param name="type"></param>
     /// <returns></returns>
     /// <exception cref="NotImplementedException"></exception>
-    public Task<Driving> GetDistanceAsync(GeoPoint origin, GeoPoint destination, String coordtype, Int32 type = 0) => throw new NotImplementedException();
+    public Task<Driving?> GetDistanceAsync(GeoPoint origin, GeoPoint destination, String? coordtype, Int32 type = 0) => throw new NotImplementedException();
     #endregion
 }
\ No newline at end of file
修改 +27 -31
diff --git a/NewLife.Map/TianDiTu.cs b/NewLife.Map/TianDiTu.cs
index 1f2e5c5..9a6d0bc 100644
--- a/NewLife.Map/TianDiTu.cs
+++ b/NewLife.Map/TianDiTu.cs
@@ -29,7 +29,7 @@ public class TianDiTu : Map, IMap
     /// <param name="url">目标Url</param>
     /// <param name="result">结果字段</param>
     /// <returns></returns>
-    protected override async Task<T> InvokeAsync<T>(String url, String result)
+    protected override async Task<T> InvokeAsync<T>(String url, String? result)
     {
         var dic = await base.InvokeAsync<IDictionary<String, Object>>(url, result);
         if (dic == null || dic.Count == 0) return default;
@@ -60,13 +60,13 @@ public class TianDiTu : Map, IMap
     /// <param name="city"></param>
     /// <param name="coordtype"></param>
     /// <returns></returns>
-    protected async Task<IDictionary<String, Object>> GetGeocoderAsync(String address, String city = null, String coordtype = null)
+    protected async Task<IDictionary<String, Object>> GetGeocoderAsync(String address, String? city = null, String? coordtype = null)
     {
         if (address.IsNullOrEmpty()) throw new ArgumentNullException(nameof(address));
 
         // 编码
         address = HttpUtility.UrlEncode(address);
-        city = HttpUtility.UrlEncode(city);
+        //city = HttpUtility.UrlEncode(city);
 
         var url = $"/geocoder?ds={{\"keyWord\":\"{address}\"}}";
 
@@ -79,23 +79,21 @@ public class TianDiTu : Map, IMap
     /// <param name="coordtype"></param>
     /// <param name="formatAddress">是否格式化地址</param>
     /// <returns></returns>
-    public async Task<GeoAddress> GetGeoAsync(String address, String city = null, String coordtype = null, Boolean formatAddress = false)
+    public async Task<GeoAddress?> GetGeoAsync(String address, String? city = null, String? coordtype = null, Boolean formatAddress = false)
     {
         var rs = await GetGeocoderAsync(address, city, coordtype);
         if (rs == null || rs.Count == 0) return null;
 
-        var gp = new GeoPoint
-        {
-            Longitude = rs["lon"].ToDouble(),
-            Latitude = rs["lat"].ToDouble()
-        };
-
         var geo = new GeoAddress
         {
-            Location = gp,
+            Location = new(rs["lon"], rs["lat"]),
         };
 
-        if (formatAddress && gp != null) geo = await GetReverseGeoAsync(gp, coordtype);
+        if (formatAddress)
+        {
+            var geo2 = await GetReverseGeoAsync(geo.Location, coordtype);
+            if (geo2 != null) geo = geo2;
+        }
 
         geo.Level = rs["level"] + "";
         geo.Confidence = rs["score"].ToInt();
@@ -112,7 +110,7 @@ public class TianDiTu : Map, IMap
     /// <param name="point"></param>
     /// <param name="coordtype">坐标系</param>
     /// <returns></returns>
-    protected async Task<IDictionary<String, Object>> GetReverseGeocoderAsync(GeoPoint point, String coordtype)
+    protected async Task<IDictionary<String, Object>> GetReverseGeocoderAsync(GeoPoint point, String? coordtype)
     {
         if (point == null || point.Longitude == 0 || point.Latitude == 0) throw new ArgumentNullException(nameof(point));
 
@@ -125,7 +123,7 @@ public class TianDiTu : Map, IMap
     /// <param name="point"></param>
     /// <param name="coordtype"></param>
     /// <returns></returns>
-    public async Task<GeoAddress> GetReverseGeoAsync(GeoPoint point, String coordtype)
+    public async Task<GeoAddress?> GetReverseGeoAsync(GeoPoint point, String? coordtype)
     {
         var rs = await GetReverseGeocoderAsync(point, coordtype);
         if (rs == null || rs.Count == 0) return null;
@@ -137,11 +135,7 @@ public class TianDiTu : Map, IMap
         };
         if (rs["location"] is IDictionary<String, Object> ds && ds.Count >= 2)
         {
-            addr.Location = new GeoPoint
-            {
-                Longitude = ds["lon"].ToDouble(),
-                Latitude = ds["lat"].ToDouble()
-            };
+            addr.Location = new(ds["lon"], ds["lat"]);
         }
 
         if (rs["addressComponent"] is IDictionary<String, Object> component)
@@ -177,9 +171,9 @@ public class TianDiTu : Map, IMap
     /// <param name="coordtype"></param>
     /// <param name="type">导航路线类型。0:最快路线,1:最短路线,2:避开高速,3:步行</param>
     /// <returns></returns>
-    public async Task<Driving> GetDistanceAsync(GeoPoint origin, GeoPoint destination, String coordtype = null, Int32 type = 0)
+    public async Task<Driving?> GetDistanceAsync(GeoPoint origin, GeoPoint destination, String? coordtype = null, Int32 type = 0)
     {
-        return await GetDistanceAsync(origin, destination, null, coordtype, type);
+        return await GetDistanceAsync(origin, destination, [], coordtype, type);
     }
 
     /// <summary>计算距离和驾车时间</summary>
@@ -192,7 +186,7 @@ public class TianDiTu : Map, IMap
     /// <param name="coordtype"></param>
     /// <param name="type">导航路线类型。0:最快路线,1:最短路线,2:避开高速,3:步行</param>
     /// <returns></returns>
-    public async Task<Driving> GetDistanceAsync(GeoPoint origin, GeoPoint destination, IList<GeoPoint> mids, String coordtype = null, Int32 type = 0)
+    public async Task<Driving?> GetDistanceAsync(GeoPoint origin, GeoPoint destination, IList<GeoPoint> mids, String? coordtype = null, Int32 type = 0)
     {
         if (origin == null || origin.Longitude < 1 && origin.Latitude < 1) throw new ArgumentNullException(nameof(origin));
         if (destination == null || destination.Longitude < 1 && destination.Latitude < 1) throw new ArgumentNullException(nameof(destination));
@@ -209,6 +203,7 @@ public class TianDiTu : Map, IMap
         if (dic == null || dic.Count == 0) return null;
 
         var html = LastString;
+        if (html.IsNullOrEmpty()) return null;
 
         var rs = new Driving
         {
@@ -231,7 +226,7 @@ public class TianDiTu : Map, IMap
     /// <param name="coordtype"></param>
     /// <param name="formatAddress"></param>
     /// <returns></returns>
-    public async Task<GeoAddress> PlaceSearchAsync(String query, String tag, String region, String coordtype = null, Boolean formatAddress = true)
+    public async Task<GeoAddress?> PlaceSearchAsync(String query, String tag, String region, String? coordtype = null, Boolean formatAddress = true)
     {
         // 编码
         query = HttpUtility.UrlEncode(query);
@@ -249,13 +244,7 @@ public class TianDiTu : Map, IMap
 
         if (rs["location"] is IDictionary<String, Object> ds && ds.Count >= 2)
         {
-            var point = new GeoPoint
-            {
-                Longitude = ds["lng"].ToDouble(),
-                Latitude = ds["lat"].ToDouble()
-            };
-
-            geo.Location = point;
+            geo.Location = new(ds["lng"], ds["lat"]);
         }
         //else if (rs["num"] is Int32 num && num > 0 && rs["name"] != null)
         //{
@@ -265,7 +254,14 @@ public class TianDiTu : Map, IMap
         else
             return null;
 
-        if (formatAddress && geo?.Location != null) geo = await GetReverseGeoAsync(geo.Location, coordtype);
+        if (formatAddress)
+        {
+            var geo2 = await GetReverseGeoAsync(geo.Location, coordtype);
+            if (geo2 != null)
+            {
+                geo = geo2;
+            }
+        }
 
         geo.Name = rs["name"] + "";
         var addr = rs["address"] + "";
修改 +13 -12
diff --git a/NewLife.Map/WeMap.cs b/NewLife.Map/WeMap.cs
index c427c0d..2b5b4b0 100644
--- a/NewLife.Map/WeMap.cs
+++ b/NewLife.Map/WeMap.cs
@@ -30,7 +30,7 @@ public class WeMap : Map, IMap
     /// <param name="url">目标Url</param>
     /// <param name="result">结果字段</param>
     /// <returns></returns>
-    protected override async Task<T> InvokeAsync<T>(String url, String result)
+    protected override async Task<T> InvokeAsync<T>(String url, String? result)
     {
         var dic = await base.InvokeAsync<IDictionary<String, Object>>(url, result);
         if (dic == null || dic.Count == 0) return default;
@@ -60,7 +60,7 @@ public class WeMap : Map, IMap
     /// https://lbs.qq.com/service/webService/webServiceGuide/webServiceGeocoder
     /// 未使用smart_address参数,(智能地址解析作为高级版服务,还可支持地址标准化整理、补全、地址切分及要素识别、提取姓名与手机号的功能。)
     /// </remarks>
-    public async Task<IDictionary<String, Object>> GetGeocoderAsync(String address, String city = null, String coordtype = null)
+    public async Task<IDictionary<String, Object>> GetGeocoderAsync(String address, String? city = null, String? coordtype = null)
     {
         if (address.IsNullOrEmpty()) throw new ArgumentNullException(nameof(address));
 
@@ -82,17 +82,18 @@ public class WeMap : Map, IMap
     /// <param name="coordtype"></param>
     /// <param name="formatAddress">是否格式化地址。</param>
     /// <returns></returns>
-    public async Task<GeoAddress> GetGeoAsync(String address, String city = null, String coordtype = null, Boolean formatAddress = false)
+    public async Task<GeoAddress?> GetGeoAsync(String address, String? city = null, String? coordtype = null, Boolean formatAddress = false)
     {
         var rs = await GetGeocoderAsync(address, city, coordtype);
         if (rs == null || rs.Count == 0) return null;
 
         if (rs["location"] is not IDictionary<String, Object> ds || ds.Count < 2) return null;
 
-        var gp = new GeoPoint { Longitude = ds["lng"].ToDouble(), Latitude = ds["lat"].ToDouble() };
+        var geo = new GeoAddress
+        {
+            Location = new(ds["lng"], ds["lat"])
+        };
 
-        var geo = new GeoAddress();
-        geo.Location = gp;
         var reader = new JsonReader();
         reader.ToObject(rs, null, geo);
 
@@ -114,7 +115,7 @@ public class WeMap : Map, IMap
 
         if (formatAddress)
         {
-            var geo2 = await GetReverseGeoAsync(gp, coordtype);
+            var geo2 = await GetReverseGeoAsync(geo.Location, coordtype);
             if (geo2 != null)
             {
                 geo2.Comprehension = geo.Comprehension;
@@ -145,7 +146,7 @@ public class WeMap : Map, IMap
     /// <remarks> 不会返回周边地点(POI)列表
     /// https://lbs.qq.com/service/webService/webServiceGuide/webServiceGcoder
     /// </remarks>
-    public async Task<IDictionary<String, Object>> GetReverseGeocoderAsync(GeoPoint point, String coordtype)
+    public async Task<IDictionary<String, Object>> GetReverseGeocoderAsync(GeoPoint point, String? coordtype)
     {
         if (point.Longitude < 0.1 || point.Latitude < 0.1) throw new ArgumentNullException(nameof(point));
 
@@ -158,7 +159,7 @@ public class WeMap : Map, IMap
     /// <param name="point"></param>
     /// <param name="coordtype"></param>
     /// <returns></returns>
-    public async Task<GeoAddress> GetReverseGeoAsync(GeoPoint point, String coordtype)
+    public async Task<GeoAddress?> GetReverseGeoAsync(GeoPoint point, String? coordtype)
     {
         var rs = await GetReverseGeocoderAsync(point, coordtype);
         if (rs == null || rs.Count == 0) return null;
@@ -211,7 +212,7 @@ public class WeMap : Map, IMap
     /// <param name="coordtype"></param>
     /// <param name="type">  1:驾车导航距离  3:自行车 2:步行规划距离 </param>
     /// <returns></returns>
-    public async Task<Driving> GetDistanceAsync(GeoPoint origin, GeoPoint destination, String coordtype, Int32 type = 1)
+    public async Task<Driving?> GetDistanceAsync(GeoPoint origin, GeoPoint destination, String? coordtype, Int32 type = 1)
     {
         if (origin == null || origin.Longitude < 1 && origin.Latitude < 1) throw new ArgumentNullException(nameof(origin));
         if (destination == null || destination.Longitude < 1 && destination.Latitude < 1) throw new ArgumentNullException(nameof(destination));
@@ -260,13 +261,13 @@ public class WeMap : Map, IMap
     /// </remarks>
     /// <param name="ip">IP</param>
     /// <returns></returns>
-    public async Task<IDictionary<String, Object>> IpLocationAsync(String ip)
+    public async Task<IDictionary<String, Object?>?> IpLocationAsync(String ip)
     {
         var url = $"/ws/location/v1/ip?ip={ip}";
 
         var dic = await InvokeAsync<IDictionary<String, Object>>(url, "result");
         if (dic == null || dic.Count == 0) return null;
-        if (dic["ad_info"] is not IDictionary<String, Object> rs) return null;
+        if (dic["ad_info"] is not IDictionary<String, Object?> rs) return null;
 
         if (dic.TryGetValue("ip", out var ipValue)) rs["ip"] = ipValue;
         if (dic["location"] is IDictionary<String, Object> locationDic)
修改 +3 -4
diff --git a/XUnitTest/AMapTests.cs b/XUnitTest/AMapTests.cs
index 858516b..e1329e0 100644
--- a/XUnitTest/AMapTests.cs
+++ b/XUnitTest/AMapTests.cs
@@ -43,10 +43,9 @@ public class AMapTests
     [Fact]
     public async void GetDistanceAsync()
     {
-        var points = new List<GeoPoint>
-        {
-            new() { Longitude = 121.51199904625513, Latitude = 31.239184419374944 },
-            new() { Longitude = 114.21892734521, Latitude = 29.575429778924 }
+        var points = new List<GeoPoint> {
+            new(121.51199904625513, 31.239184419374944),
+            new(114.21892734521, 29.575429778924)
         };
 
         var map = _map;
修改 +6 -8
diff --git a/XUnitTest/BaiduMapTests.cs b/XUnitTest/BaiduMapTests.cs
index bb54d59..c352ec2 100644
--- a/XUnitTest/BaiduMapTests.cs
+++ b/XUnitTest/BaiduMapTests.cs
@@ -62,10 +62,9 @@ public class BaiduMapTests
     [Fact]
     public async void GetDistanceAsync()
     {
-        var points = new List<GeoPoint>
-        {
-            new() { Longitude = 121.51199904625513, Latitude = 31.239184419374944 },
-            new() { Longitude = 114.21892734521, Latitude = 29.575429778924 }
+        var points = new List<GeoPoint> {
+            new(121.51199904625513, 31.239184419374944),
+            new(114.21892734521, 29.575429778924)
         };
 
         var map = _map;
@@ -79,10 +78,9 @@ public class BaiduMapTests
     [Fact]
     public async void ConvertAsync()
     {
-        var points = new List<GeoPoint>
-        {
-            new() { Longitude = 121.51199904625513, Latitude = 31.239184419374944 },
-            new() { Longitude = 114.21892734521, Latitude = 29.575429778924 }
+        var points = new List<GeoPoint> {
+            new(121.51199904625513, 31.239184419374944),
+            new(114.21892734521, 29.575429778924)
         };
 
         var map = _map;
修改 +8 -10
diff --git a/XUnitTest/TianDiMapTests.cs b/XUnitTest/TianDiMapTests.cs
index da96c01..9550a2d 100644
--- a/XUnitTest/TianDiMapTests.cs
+++ b/XUnitTest/TianDiMapTests.cs
@@ -47,10 +47,9 @@ public class TianDiMapTests
     [Fact]
     public async void GetDistanceAsync()
     {
-        var points = new List<GeoPoint>
-        {
-            new() { Longitude = 121.51199904625513, Latitude = 31.239184419374944 },
-            new() { Longitude = 114.21892734521, Latitude = 29.575429778924 },
+        var points = new List<GeoPoint> {
+            new(121.51199904625513, 31.239184419374944),
+            new(114.21892734521, 29.575429778924)
         };
 
         var map = _map;
@@ -64,12 +63,11 @@ public class TianDiMapTests
     [Fact]
     public async void GetDistanceAsync2()
     {
-        var points = new List<GeoPoint>
-        {
-            new() { Longitude = 121.51199904625513, Latitude = 31.239184419374944 },
-            new() { Longitude = 118.21, Latitude = 30.57 },
-            new() { Longitude = 116.21, Latitude = 29.97 },
-            new() { Longitude = 114.21892734521, Latitude = 29.575429778924 },
+        var points = new List<GeoPoint> {
+            new(121.51199904625513, 31.239184419374944),
+            new(118.21, 30.57),
+            new(116.21, 29.97),
+            new(114.21892734521, 29.575429778924)
         };
 
         var map = _map;
修改 +3 -4
diff --git a/XUnitTest/WeMapTests.cs b/XUnitTest/WeMapTests.cs
index 81088bd..e616c35 100644
--- a/XUnitTest/WeMapTests.cs
+++ b/XUnitTest/WeMapTests.cs
@@ -47,10 +47,9 @@ public class WeMapTests
     [Fact]
     public async void GetDistanceAsync()
     {
-        var points = new List<GeoPoint>
-        {
-            new() { Longitude = 121.51199904625513, Latitude = 31.239184419374944 },
-            new() { Longitude = 114.21892734521, Latitude = 29.575429778924 }
+        var points = new List<GeoPoint> {
+            new(121.51199904625513, 31.239184419374944),
+            new(114.21892734521, 29.575429778924)
         };
 
         var map = _map;