using System.Collections.Generic;
using System.Threading.Tasks;
public class WorldCityTable
public double Lat { get; set; }
public double Lng { get; set; }
public string City { get; set; }
public interface IDatabase
Task<List<WorldCityTable>> QueryAsync<WorldCityTable>(string sql, params object[] parameters);
public class NearestCityFinder
private readonly IDatabase _database;
public NearestCityFinder(IDatabase database)
_database = database ?? throw new ArgumentNullException(nameof(database));
public async Task<WorldCityTable> GetNearestCityAsync(double currentLat, double currentLng)
if (currentLat < -90 || currentLat > 90)
throw new ArgumentException("Latitude must be between -90 and 90 degrees.", nameof(currentLat));
if (currentLng < -180 || currentLng > 180)
throw new ArgumentException("Longitude must be between -180 and 180 degrees.", nameof(currentLng));
ORDER BY ST_Distance(ST_MakePoint(Lng, Lat), ST_MakePoint(@lng, @lat))
var cities = await _database.QueryAsync<WorldCityTable>(sqlQuery, new { lat = currentLat, lng = currentLng });
return cities.FirstOrDefault();
Console.WriteLine($"Error executing database query: {ex.Message}");
public static async Task Main(string[] args)
var mockDatabase = new MockDatabase();
mockDatabase.AddCity(new WorldCityTable { City = "New York", Lat = 40.7128, Lng = -74.0060 });
mockDatabase.AddCity(new WorldCityTable { City = "Los Angeles", Lat = 34.0522, Lng = -118.2437 });
mockDatabase.AddCity(new WorldCityTable { City = "London", Lat = 51.5074, Lng = 0.1278 });
mockDatabase.AddCity(new WorldCityTable { City = "Sydney", Lat = -33.8688, Lng = 151.2093 });
var nearestCityFinder = new NearestCityFinder(mockDatabase);
double longitude = -118.0;
var nearestCity = await nearestCityFinder.GetNearestCityAsync(latitude, longitude);
Console.WriteLine($"The nearest city to ({latitude}, {longitude}) is {nearestCity.City} (Lat: {nearestCity.Lat}, Lng: {nearestCity.Lng})");
Console.WriteLine("No cities found in the database.");
catch (ArgumentException ex)
Console.WriteLine($"Error: {ex.Message}");
Console.WriteLine($"An unexpected error occurred: {ex.Message}");
public class MockDatabase : IDatabase
private readonly List<WorldCityTable> _cities = new List<WorldCityTable>();
public void AddCity(WorldCityTable city)
public async Task<List<WorldCityTable>> QueryAsync<WorldCityTable>(string sql, params object[] parameters)
if (sql.Contains("ST_Distance"))
var lat = (double)((dynamic)parameters[0]).lat;
var lng = (double)((dynamic)parameters[0]).lng;
return _cities.OrderBy(city => Math.Pow(city.Lat - lat, 2) + Math.Pow(city.Lng - lng, 2)).Take(1).Cast<WorldCityTable>().ToList();
return await Task.FromResult(_cities.Cast<WorldCityTable>().ToList());