Finding the nearest agents to a customer using IComparableMulti-tiered sorting using custom IComparerIComparable comparisionWebAPI - Return models vs entity and partial class with meta dataExceptions or something else?IComparable implementation for a class representing a versionSorting algorithmFinding travel distance between airportsRectangle Classpancake sorting using pythonSorting table using multiple columns

...And they were stumped for a long time

What is the use case for non-breathable waterproof pants?

Can we assume that a hash function with high collision resistance also means highly uniform distribution?

Why did Jon Snow do this immoral act if he is so honorable?

Why sampling a periodic signal doesn't yield a periodic discrete signal?

Variable declaraton with extra in C

Of strange atmospheres - the survivable but unbreathable

Must a warlock replace spells with new spells of exactly their Pact Magic spell slot level?

Gravitational Force Between Numbers

Which European Languages are not Indo-European?

How would a developer who mostly fixed bugs for years at a company call out their contributions in their CV?

Python program for fibonacci sequence using a recursive function

Is "vegetable base" a common term in English?

How to keep consistency across the application architecture as a team grows?

Using too much dialogue?

Is there an idiom that means that you are in a very strong negotiation position in a negotiation?

Navigating a quick return to previous employer

Is superuser the same as root?

Why does Bran want to find Drogon?

Why would a rational buyer offer to buy with no conditions precedent?

Are cells guaranteed to get at least one mitochondrion when they divide?

Can a UK national work as a paid shop assistant in the USA?

Where is Jon going?

Why isn't 'chemically-strengthened glass' made with potassium carbonate? To begin with?



Finding the nearest agents to a customer using IComparable


Multi-tiered sorting using custom IComparerIComparable comparisionWebAPI - Return models vs entity and partial class with meta dataExceptions or something else?IComparable implementation for a class representing a versionSorting algorithmFinding travel distance between airportsRectangle Classpancake sorting using pythonSorting table using multiple columns






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








5












$begingroup$


I got a C# class:



public class Agent 

public string AgentId set; get;
public double Longitude set; get;
public double Latitude set; get;



There are several agents in several different locations. During the program's lifetime, they can receive a call to another (latitude, longitude) point which is unknown during runtime. I got an API to calculate the distance in meters between their location and the given point. What I need eventually is to find the 5 closest agents to the given point.



What I did in order to achieve this is adding another class:



public class AgentDistance : Agent, IComparable<AgentDistance>


public AgentDistance(Agent agent)

if(agent == null)

throw new Exception("Can't initalize agent with distance since agent is null");

this.AgentId = agent.AgentId;
this.Latitude = agent.Latitude;
this.Longitude = agent.Longitude;


public double Distance set; get;

public int CompareTo(AgentDistance other)

if(other == null)

return 1;

return Distance.CompareTo(other.Distance);




And the usage:



var agents = db.GetAgents();
if(agents == null || agents.Count == 0)

Console.WriteLine("No Results");

List<AgentDistance> agentsWithDistance = new List<AgentDistance>();
foreach(Agent agent in agents)

double res = ws.GetDistanceMeters(agent.Latitude, agent.Longitude, customerLatitude, customerLongitude);
agentsWithDistance.Add(new AgentDistance(agent) Distance = res );

agentsWithDistance.Sort();
for(int i = 0; i < 5; i++)

Console.WriteLine(string.Format("agent_id: 0 distance: 1 m", agentsWithDistance[i].AgentId, agentsWithDistance[i].Distance));



It works, but is there a more elegant way to do it? I'm not sure if adding another class might be a bit redundant since all it does is just adding a property for sorting, but adding the distance property to the Agent class, doesn't make so much sense.










share|improve this question









New contributor



Yonatan Nir is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$


















    5












    $begingroup$


    I got a C# class:



    public class Agent 

    public string AgentId set; get;
    public double Longitude set; get;
    public double Latitude set; get;



    There are several agents in several different locations. During the program's lifetime, they can receive a call to another (latitude, longitude) point which is unknown during runtime. I got an API to calculate the distance in meters between their location and the given point. What I need eventually is to find the 5 closest agents to the given point.



    What I did in order to achieve this is adding another class:



    public class AgentDistance : Agent, IComparable<AgentDistance>


    public AgentDistance(Agent agent)

    if(agent == null)

    throw new Exception("Can't initalize agent with distance since agent is null");

    this.AgentId = agent.AgentId;
    this.Latitude = agent.Latitude;
    this.Longitude = agent.Longitude;


    public double Distance set; get;

    public int CompareTo(AgentDistance other)

    if(other == null)

    return 1;

    return Distance.CompareTo(other.Distance);




    And the usage:



    var agents = db.GetAgents();
    if(agents == null || agents.Count == 0)

    Console.WriteLine("No Results");

    List<AgentDistance> agentsWithDistance = new List<AgentDistance>();
    foreach(Agent agent in agents)

    double res = ws.GetDistanceMeters(agent.Latitude, agent.Longitude, customerLatitude, customerLongitude);
    agentsWithDistance.Add(new AgentDistance(agent) Distance = res );

    agentsWithDistance.Sort();
    for(int i = 0; i < 5; i++)

    Console.WriteLine(string.Format("agent_id: 0 distance: 1 m", agentsWithDistance[i].AgentId, agentsWithDistance[i].Distance));



    It works, but is there a more elegant way to do it? I'm not sure if adding another class might be a bit redundant since all it does is just adding a property for sorting, but adding the distance property to the Agent class, doesn't make so much sense.










    share|improve this question









    New contributor



    Yonatan Nir is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.






    $endgroup$














      5












      5








      5





      $begingroup$


      I got a C# class:



      public class Agent 

      public string AgentId set; get;
      public double Longitude set; get;
      public double Latitude set; get;



      There are several agents in several different locations. During the program's lifetime, they can receive a call to another (latitude, longitude) point which is unknown during runtime. I got an API to calculate the distance in meters between their location and the given point. What I need eventually is to find the 5 closest agents to the given point.



      What I did in order to achieve this is adding another class:



      public class AgentDistance : Agent, IComparable<AgentDistance>


      public AgentDistance(Agent agent)

      if(agent == null)

      throw new Exception("Can't initalize agent with distance since agent is null");

      this.AgentId = agent.AgentId;
      this.Latitude = agent.Latitude;
      this.Longitude = agent.Longitude;


      public double Distance set; get;

      public int CompareTo(AgentDistance other)

      if(other == null)

      return 1;

      return Distance.CompareTo(other.Distance);




      And the usage:



      var agents = db.GetAgents();
      if(agents == null || agents.Count == 0)

      Console.WriteLine("No Results");

      List<AgentDistance> agentsWithDistance = new List<AgentDistance>();
      foreach(Agent agent in agents)

      double res = ws.GetDistanceMeters(agent.Latitude, agent.Longitude, customerLatitude, customerLongitude);
      agentsWithDistance.Add(new AgentDistance(agent) Distance = res );

      agentsWithDistance.Sort();
      for(int i = 0; i < 5; i++)

      Console.WriteLine(string.Format("agent_id: 0 distance: 1 m", agentsWithDistance[i].AgentId, agentsWithDistance[i].Distance));



      It works, but is there a more elegant way to do it? I'm not sure if adding another class might be a bit redundant since all it does is just adding a property for sorting, but adding the distance property to the Agent class, doesn't make so much sense.










      share|improve this question









      New contributor



      Yonatan Nir is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      $endgroup$




      I got a C# class:



      public class Agent 

      public string AgentId set; get;
      public double Longitude set; get;
      public double Latitude set; get;



      There are several agents in several different locations. During the program's lifetime, they can receive a call to another (latitude, longitude) point which is unknown during runtime. I got an API to calculate the distance in meters between their location and the given point. What I need eventually is to find the 5 closest agents to the given point.



      What I did in order to achieve this is adding another class:



      public class AgentDistance : Agent, IComparable<AgentDistance>


      public AgentDistance(Agent agent)

      if(agent == null)

      throw new Exception("Can't initalize agent with distance since agent is null");

      this.AgentId = agent.AgentId;
      this.Latitude = agent.Latitude;
      this.Longitude = agent.Longitude;


      public double Distance set; get;

      public int CompareTo(AgentDistance other)

      if(other == null)

      return 1;

      return Distance.CompareTo(other.Distance);




      And the usage:



      var agents = db.GetAgents();
      if(agents == null || agents.Count == 0)

      Console.WriteLine("No Results");

      List<AgentDistance> agentsWithDistance = new List<AgentDistance>();
      foreach(Agent agent in agents)

      double res = ws.GetDistanceMeters(agent.Latitude, agent.Longitude, customerLatitude, customerLongitude);
      agentsWithDistance.Add(new AgentDistance(agent) Distance = res );

      agentsWithDistance.Sort();
      for(int i = 0; i < 5; i++)

      Console.WriteLine(string.Format("agent_id: 0 distance: 1 m", agentsWithDistance[i].AgentId, agentsWithDistance[i].Distance));



      It works, but is there a more elegant way to do it? I'm not sure if adding another class might be a bit redundant since all it does is just adding a property for sorting, but adding the distance property to the Agent class, doesn't make so much sense.







      c# sorting geospatial






      share|improve this question









      New contributor



      Yonatan Nir is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.










      share|improve this question









      New contributor



      Yonatan Nir is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.








      share|improve this question




      share|improve this question








      edited 45 mins ago









      200_success

      132k20159426




      132k20159426






      New contributor



      Yonatan Nir is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.








      asked 13 hours ago









      Yonatan NirYonatan Nir

      1284




      1284




      New contributor



      Yonatan Nir is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.




      New contributor




      Yonatan Nir is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






















          3 Answers
          3






          active

          oldest

          votes


















          7












          $begingroup$


          var agents = db.GetAgents();
          if(agents == null || agents.Count == 0)

          Console.WriteLine("No Results");




          You should exit your application/code block when you detect an invalid state. Here even if "No Results" is printed, the app will still run into a NullReferenceException or IndexOutOfRangeException in the next few steps. Also, talking of IndexOutOfRangeException, there is no check against if there is at least 5 agents in your db.



          Instead of creating an IComparable, you can just use linq to sort directly. But, since in your case, you also need to print out the distance (the value used for sorting), we will need to create an anonymous class to hold it:



          var agents = db.GetAgents();
          if(agents == null || agents.Count == 0)

          Console.WriteLine("No Results");
          return;


          var nearestAgents = agents
          .Select(x => new

          x.AgentId,
          x.Latitude, x.Longitude,
          DistanceToCustomer = ws.GetDistanceMeters(x.Latitude, x.Longitude, customerLatitude, customerLongitude)
          )
          .OrderBy(x => x.DistanceToCustomer);
          foreach (var agent in nearestAgents.Take(5))

          Console.WriteLine($"agent_id: agent.AgentId distance: agent.DistanceToCustomer m");



          The .Take(5) ensures that only 5 agent will be printed out, or less.






          share|improve this answer











          $endgroup$












          • $begingroup$
            The anonymous class doesn't need the x.Latitude and x.Longitude fields.
            $endgroup$
            – 200_success
            43 mins ago


















          4












          $begingroup$

          I'd say you have the following options:




          1. Keep that new class if you think it's relevant in your business. Here, it should be important to know if the logic of calculate the distance should be on that web service (I assume that 'ws' variable means that) or within your model (i.e., the 'Agent' class).


          2. Use an anonymous class if you think you won't pass that info to another method.


          3. Use a dictionary if you think it's not relevant in your business but will pass that info to another method.

          Personally, I'd go for the first one since it's the most natural to me. By the way, I'd use LINQ's OrderBy instead of implementing the IComparable interface; again, for expressiveness.






          share|improve this answer









          $endgroup$




















            0












            $begingroup$

            I think, I would hold on to your decorator pattern because it is more reusable than the selection with anonymous objects.



             public class DistancedAgent : Agent

            public DistancedAgent(Agent source, double distance)

            AgentId = source.AgentId;
            Latitude = source.Latitude;
            Longitude = source.Longitude;
            Distance = distance;


            public double Distance get;

            public override string ToString()

            return $"Latitude, Longitude => Distance";




            You could extent Agent with some converter methods:



             public static class Extensions

            public static DistancedAgent WithDistance(this Agent agent, Func<Agent, double> getDistance)

            return new DistancedAgent(agent, getDistance(agent));


            public static DistancedAgent WithDistance(this Agent agent, IDistanceProvider distanceProvider)

            return new DistancedAgent(agent, distanceProvider.GetDistance(agent));


            public static IEnumerable<DistancedAgent> WithDistance(this IEnumerable<Agent> agents, Func<Agent, double> getDistance)

            return agents?.Where(a => a != null).Select(a => a.WithDistance(getDistance)) ?? new DistancedAgent[0];


            public static IEnumerable<DistancedAgent> WithDistance(this IEnumerable<Agent> agents, IDistanceProvider distanceProvider)

            return agents?.Where(a => a != null).Select(a => a.WithDistance(distanceProvider)) ?? new DistancedAgent[0];




            where IDistanceProvider is



             public interface IDistanceProvider

            double GetDistance(Agent agent);




            In the concrete use case it ends up with code like this:



             var agents = db.GetAgents();

            Func<Agent, double> getDistance = a => ws.GetDistanceMeters(a.Latitude, a.Longitude, customerLatitude, customerLongitude);

            foreach (DistancedAgent dAgent in agents.WithDistance(getDistance).OrderBy(da => da.Distance).Take(5))

            Console.WriteLine(dAgent);



            which is easy to understand and maintain and you have a setup that can be used wherever needed.






            share|improve this answer









            $endgroup$













              Your Answer






              StackExchange.ifUsing("editor", function ()
              StackExchange.using("externalEditor", function ()
              StackExchange.using("snippets", function ()
              StackExchange.snippets.init();
              );
              );
              , "code-snippets");

              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "196"
              ;
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function()
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled)
              StackExchange.using("snippets", function()
              createEditor();
              );

              else
              createEditor();

              );

              function createEditor()
              StackExchange.prepareEditor(
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: false,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              imageUploader:
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              ,
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );






              Yonatan Nir is a new contributor. Be nice, and check out our Code of Conduct.









              draft saved

              draft discarded


















              StackExchange.ready(
              function ()
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f220650%2ffinding-the-nearest-agents-to-a-customer-using-icomparable%23new-answer', 'question_page');

              );

              Post as a guest















              Required, but never shown

























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              7












              $begingroup$


              var agents = db.GetAgents();
              if(agents == null || agents.Count == 0)

              Console.WriteLine("No Results");




              You should exit your application/code block when you detect an invalid state. Here even if "No Results" is printed, the app will still run into a NullReferenceException or IndexOutOfRangeException in the next few steps. Also, talking of IndexOutOfRangeException, there is no check against if there is at least 5 agents in your db.



              Instead of creating an IComparable, you can just use linq to sort directly. But, since in your case, you also need to print out the distance (the value used for sorting), we will need to create an anonymous class to hold it:



              var agents = db.GetAgents();
              if(agents == null || agents.Count == 0)

              Console.WriteLine("No Results");
              return;


              var nearestAgents = agents
              .Select(x => new

              x.AgentId,
              x.Latitude, x.Longitude,
              DistanceToCustomer = ws.GetDistanceMeters(x.Latitude, x.Longitude, customerLatitude, customerLongitude)
              )
              .OrderBy(x => x.DistanceToCustomer);
              foreach (var agent in nearestAgents.Take(5))

              Console.WriteLine($"agent_id: agent.AgentId distance: agent.DistanceToCustomer m");



              The .Take(5) ensures that only 5 agent will be printed out, or less.






              share|improve this answer











              $endgroup$












              • $begingroup$
                The anonymous class doesn't need the x.Latitude and x.Longitude fields.
                $endgroup$
                – 200_success
                43 mins ago















              7












              $begingroup$


              var agents = db.GetAgents();
              if(agents == null || agents.Count == 0)

              Console.WriteLine("No Results");




              You should exit your application/code block when you detect an invalid state. Here even if "No Results" is printed, the app will still run into a NullReferenceException or IndexOutOfRangeException in the next few steps. Also, talking of IndexOutOfRangeException, there is no check against if there is at least 5 agents in your db.



              Instead of creating an IComparable, you can just use linq to sort directly. But, since in your case, you also need to print out the distance (the value used for sorting), we will need to create an anonymous class to hold it:



              var agents = db.GetAgents();
              if(agents == null || agents.Count == 0)

              Console.WriteLine("No Results");
              return;


              var nearestAgents = agents
              .Select(x => new

              x.AgentId,
              x.Latitude, x.Longitude,
              DistanceToCustomer = ws.GetDistanceMeters(x.Latitude, x.Longitude, customerLatitude, customerLongitude)
              )
              .OrderBy(x => x.DistanceToCustomer);
              foreach (var agent in nearestAgents.Take(5))

              Console.WriteLine($"agent_id: agent.AgentId distance: agent.DistanceToCustomer m");



              The .Take(5) ensures that only 5 agent will be printed out, or less.






              share|improve this answer











              $endgroup$












              • $begingroup$
                The anonymous class doesn't need the x.Latitude and x.Longitude fields.
                $endgroup$
                – 200_success
                43 mins ago













              7












              7








              7





              $begingroup$


              var agents = db.GetAgents();
              if(agents == null || agents.Count == 0)

              Console.WriteLine("No Results");




              You should exit your application/code block when you detect an invalid state. Here even if "No Results" is printed, the app will still run into a NullReferenceException or IndexOutOfRangeException in the next few steps. Also, talking of IndexOutOfRangeException, there is no check against if there is at least 5 agents in your db.



              Instead of creating an IComparable, you can just use linq to sort directly. But, since in your case, you also need to print out the distance (the value used for sorting), we will need to create an anonymous class to hold it:



              var agents = db.GetAgents();
              if(agents == null || agents.Count == 0)

              Console.WriteLine("No Results");
              return;


              var nearestAgents = agents
              .Select(x => new

              x.AgentId,
              x.Latitude, x.Longitude,
              DistanceToCustomer = ws.GetDistanceMeters(x.Latitude, x.Longitude, customerLatitude, customerLongitude)
              )
              .OrderBy(x => x.DistanceToCustomer);
              foreach (var agent in nearestAgents.Take(5))

              Console.WriteLine($"agent_id: agent.AgentId distance: agent.DistanceToCustomer m");



              The .Take(5) ensures that only 5 agent will be printed out, or less.






              share|improve this answer











              $endgroup$




              var agents = db.GetAgents();
              if(agents == null || agents.Count == 0)

              Console.WriteLine("No Results");




              You should exit your application/code block when you detect an invalid state. Here even if "No Results" is printed, the app will still run into a NullReferenceException or IndexOutOfRangeException in the next few steps. Also, talking of IndexOutOfRangeException, there is no check against if there is at least 5 agents in your db.



              Instead of creating an IComparable, you can just use linq to sort directly. But, since in your case, you also need to print out the distance (the value used for sorting), we will need to create an anonymous class to hold it:



              var agents = db.GetAgents();
              if(agents == null || agents.Count == 0)

              Console.WriteLine("No Results");
              return;


              var nearestAgents = agents
              .Select(x => new

              x.AgentId,
              x.Latitude, x.Longitude,
              DistanceToCustomer = ws.GetDistanceMeters(x.Latitude, x.Longitude, customerLatitude, customerLongitude)
              )
              .OrderBy(x => x.DistanceToCustomer);
              foreach (var agent in nearestAgents.Take(5))

              Console.WriteLine($"agent_id: agent.AgentId distance: agent.DistanceToCustomer m");



              The .Take(5) ensures that only 5 agent will be printed out, or less.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited 12 hours ago

























              answered 12 hours ago









              Xiaoy312Xiaoy312

              2,9961016




              2,9961016











              • $begingroup$
                The anonymous class doesn't need the x.Latitude and x.Longitude fields.
                $endgroup$
                – 200_success
                43 mins ago
















              • $begingroup$
                The anonymous class doesn't need the x.Latitude and x.Longitude fields.
                $endgroup$
                – 200_success
                43 mins ago















              $begingroup$
              The anonymous class doesn't need the x.Latitude and x.Longitude fields.
              $endgroup$
              – 200_success
              43 mins ago




              $begingroup$
              The anonymous class doesn't need the x.Latitude and x.Longitude fields.
              $endgroup$
              – 200_success
              43 mins ago













              4












              $begingroup$

              I'd say you have the following options:




              1. Keep that new class if you think it's relevant in your business. Here, it should be important to know if the logic of calculate the distance should be on that web service (I assume that 'ws' variable means that) or within your model (i.e., the 'Agent' class).


              2. Use an anonymous class if you think you won't pass that info to another method.


              3. Use a dictionary if you think it's not relevant in your business but will pass that info to another method.

              Personally, I'd go for the first one since it's the most natural to me. By the way, I'd use LINQ's OrderBy instead of implementing the IComparable interface; again, for expressiveness.






              share|improve this answer









              $endgroup$

















                4












                $begingroup$

                I'd say you have the following options:




                1. Keep that new class if you think it's relevant in your business. Here, it should be important to know if the logic of calculate the distance should be on that web service (I assume that 'ws' variable means that) or within your model (i.e., the 'Agent' class).


                2. Use an anonymous class if you think you won't pass that info to another method.


                3. Use a dictionary if you think it's not relevant in your business but will pass that info to another method.

                Personally, I'd go for the first one since it's the most natural to me. By the way, I'd use LINQ's OrderBy instead of implementing the IComparable interface; again, for expressiveness.






                share|improve this answer









                $endgroup$















                  4












                  4








                  4





                  $begingroup$

                  I'd say you have the following options:




                  1. Keep that new class if you think it's relevant in your business. Here, it should be important to know if the logic of calculate the distance should be on that web service (I assume that 'ws' variable means that) or within your model (i.e., the 'Agent' class).


                  2. Use an anonymous class if you think you won't pass that info to another method.


                  3. Use a dictionary if you think it's not relevant in your business but will pass that info to another method.

                  Personally, I'd go for the first one since it's the most natural to me. By the way, I'd use LINQ's OrderBy instead of implementing the IComparable interface; again, for expressiveness.






                  share|improve this answer









                  $endgroup$



                  I'd say you have the following options:




                  1. Keep that new class if you think it's relevant in your business. Here, it should be important to know if the logic of calculate the distance should be on that web service (I assume that 'ws' variable means that) or within your model (i.e., the 'Agent' class).


                  2. Use an anonymous class if you think you won't pass that info to another method.


                  3. Use a dictionary if you think it's not relevant in your business but will pass that info to another method.

                  Personally, I'd go for the first one since it's the most natural to me. By the way, I'd use LINQ's OrderBy instead of implementing the IComparable interface; again, for expressiveness.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 12 hours ago









                  A Bravo DevA Bravo Dev

                  599210




                  599210





















                      0












                      $begingroup$

                      I think, I would hold on to your decorator pattern because it is more reusable than the selection with anonymous objects.



                       public class DistancedAgent : Agent

                      public DistancedAgent(Agent source, double distance)

                      AgentId = source.AgentId;
                      Latitude = source.Latitude;
                      Longitude = source.Longitude;
                      Distance = distance;


                      public double Distance get;

                      public override string ToString()

                      return $"Latitude, Longitude => Distance";




                      You could extent Agent with some converter methods:



                       public static class Extensions

                      public static DistancedAgent WithDistance(this Agent agent, Func<Agent, double> getDistance)

                      return new DistancedAgent(agent, getDistance(agent));


                      public static DistancedAgent WithDistance(this Agent agent, IDistanceProvider distanceProvider)

                      return new DistancedAgent(agent, distanceProvider.GetDistance(agent));


                      public static IEnumerable<DistancedAgent> WithDistance(this IEnumerable<Agent> agents, Func<Agent, double> getDistance)

                      return agents?.Where(a => a != null).Select(a => a.WithDistance(getDistance)) ?? new DistancedAgent[0];


                      public static IEnumerable<DistancedAgent> WithDistance(this IEnumerable<Agent> agents, IDistanceProvider distanceProvider)

                      return agents?.Where(a => a != null).Select(a => a.WithDistance(distanceProvider)) ?? new DistancedAgent[0];




                      where IDistanceProvider is



                       public interface IDistanceProvider

                      double GetDistance(Agent agent);




                      In the concrete use case it ends up with code like this:



                       var agents = db.GetAgents();

                      Func<Agent, double> getDistance = a => ws.GetDistanceMeters(a.Latitude, a.Longitude, customerLatitude, customerLongitude);

                      foreach (DistancedAgent dAgent in agents.WithDistance(getDistance).OrderBy(da => da.Distance).Take(5))

                      Console.WriteLine(dAgent);



                      which is easy to understand and maintain and you have a setup that can be used wherever needed.






                      share|improve this answer









                      $endgroup$

















                        0












                        $begingroup$

                        I think, I would hold on to your decorator pattern because it is more reusable than the selection with anonymous objects.



                         public class DistancedAgent : Agent

                        public DistancedAgent(Agent source, double distance)

                        AgentId = source.AgentId;
                        Latitude = source.Latitude;
                        Longitude = source.Longitude;
                        Distance = distance;


                        public double Distance get;

                        public override string ToString()

                        return $"Latitude, Longitude => Distance";




                        You could extent Agent with some converter methods:



                         public static class Extensions

                        public static DistancedAgent WithDistance(this Agent agent, Func<Agent, double> getDistance)

                        return new DistancedAgent(agent, getDistance(agent));


                        public static DistancedAgent WithDistance(this Agent agent, IDistanceProvider distanceProvider)

                        return new DistancedAgent(agent, distanceProvider.GetDistance(agent));


                        public static IEnumerable<DistancedAgent> WithDistance(this IEnumerable<Agent> agents, Func<Agent, double> getDistance)

                        return agents?.Where(a => a != null).Select(a => a.WithDistance(getDistance)) ?? new DistancedAgent[0];


                        public static IEnumerable<DistancedAgent> WithDistance(this IEnumerable<Agent> agents, IDistanceProvider distanceProvider)

                        return agents?.Where(a => a != null).Select(a => a.WithDistance(distanceProvider)) ?? new DistancedAgent[0];




                        where IDistanceProvider is



                         public interface IDistanceProvider

                        double GetDistance(Agent agent);




                        In the concrete use case it ends up with code like this:



                         var agents = db.GetAgents();

                        Func<Agent, double> getDistance = a => ws.GetDistanceMeters(a.Latitude, a.Longitude, customerLatitude, customerLongitude);

                        foreach (DistancedAgent dAgent in agents.WithDistance(getDistance).OrderBy(da => da.Distance).Take(5))

                        Console.WriteLine(dAgent);



                        which is easy to understand and maintain and you have a setup that can be used wherever needed.






                        share|improve this answer









                        $endgroup$















                          0












                          0








                          0





                          $begingroup$

                          I think, I would hold on to your decorator pattern because it is more reusable than the selection with anonymous objects.



                           public class DistancedAgent : Agent

                          public DistancedAgent(Agent source, double distance)

                          AgentId = source.AgentId;
                          Latitude = source.Latitude;
                          Longitude = source.Longitude;
                          Distance = distance;


                          public double Distance get;

                          public override string ToString()

                          return $"Latitude, Longitude => Distance";




                          You could extent Agent with some converter methods:



                           public static class Extensions

                          public static DistancedAgent WithDistance(this Agent agent, Func<Agent, double> getDistance)

                          return new DistancedAgent(agent, getDistance(agent));


                          public static DistancedAgent WithDistance(this Agent agent, IDistanceProvider distanceProvider)

                          return new DistancedAgent(agent, distanceProvider.GetDistance(agent));


                          public static IEnumerable<DistancedAgent> WithDistance(this IEnumerable<Agent> agents, Func<Agent, double> getDistance)

                          return agents?.Where(a => a != null).Select(a => a.WithDistance(getDistance)) ?? new DistancedAgent[0];


                          public static IEnumerable<DistancedAgent> WithDistance(this IEnumerable<Agent> agents, IDistanceProvider distanceProvider)

                          return agents?.Where(a => a != null).Select(a => a.WithDistance(distanceProvider)) ?? new DistancedAgent[0];




                          where IDistanceProvider is



                           public interface IDistanceProvider

                          double GetDistance(Agent agent);




                          In the concrete use case it ends up with code like this:



                           var agents = db.GetAgents();

                          Func<Agent, double> getDistance = a => ws.GetDistanceMeters(a.Latitude, a.Longitude, customerLatitude, customerLongitude);

                          foreach (DistancedAgent dAgent in agents.WithDistance(getDistance).OrderBy(da => da.Distance).Take(5))

                          Console.WriteLine(dAgent);



                          which is easy to understand and maintain and you have a setup that can be used wherever needed.






                          share|improve this answer









                          $endgroup$



                          I think, I would hold on to your decorator pattern because it is more reusable than the selection with anonymous objects.



                           public class DistancedAgent : Agent

                          public DistancedAgent(Agent source, double distance)

                          AgentId = source.AgentId;
                          Latitude = source.Latitude;
                          Longitude = source.Longitude;
                          Distance = distance;


                          public double Distance get;

                          public override string ToString()

                          return $"Latitude, Longitude => Distance";




                          You could extent Agent with some converter methods:



                           public static class Extensions

                          public static DistancedAgent WithDistance(this Agent agent, Func<Agent, double> getDistance)

                          return new DistancedAgent(agent, getDistance(agent));


                          public static DistancedAgent WithDistance(this Agent agent, IDistanceProvider distanceProvider)

                          return new DistancedAgent(agent, distanceProvider.GetDistance(agent));


                          public static IEnumerable<DistancedAgent> WithDistance(this IEnumerable<Agent> agents, Func<Agent, double> getDistance)

                          return agents?.Where(a => a != null).Select(a => a.WithDistance(getDistance)) ?? new DistancedAgent[0];


                          public static IEnumerable<DistancedAgent> WithDistance(this IEnumerable<Agent> agents, IDistanceProvider distanceProvider)

                          return agents?.Where(a => a != null).Select(a => a.WithDistance(distanceProvider)) ?? new DistancedAgent[0];




                          where IDistanceProvider is



                           public interface IDistanceProvider

                          double GetDistance(Agent agent);




                          In the concrete use case it ends up with code like this:



                           var agents = db.GetAgents();

                          Func<Agent, double> getDistance = a => ws.GetDistanceMeters(a.Latitude, a.Longitude, customerLatitude, customerLongitude);

                          foreach (DistancedAgent dAgent in agents.WithDistance(getDistance).OrderBy(da => da.Distance).Take(5))

                          Console.WriteLine(dAgent);



                          which is easy to understand and maintain and you have a setup that can be used wherever needed.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered 1 hour ago









                          Henrik HansenHenrik Hansen

                          8,86711332




                          8,86711332




















                              Yonatan Nir is a new contributor. Be nice, and check out our Code of Conduct.









                              draft saved

                              draft discarded


















                              Yonatan Nir is a new contributor. Be nice, and check out our Code of Conduct.












                              Yonatan Nir is a new contributor. Be nice, and check out our Code of Conduct.











                              Yonatan Nir is a new contributor. Be nice, and check out our Code of Conduct.














                              Thanks for contributing an answer to Code Review Stack Exchange!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid


                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.

                              Use MathJax to format equations. MathJax reference.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f220650%2ffinding-the-nearest-agents-to-a-customer-using-icomparable%23new-answer', 'question_page');

                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Log på Navigationsmenu

                              Wonderful Copenhagen (sang) Eksterne henvisninger | NavigationsmenurSide på frankloesser.comWonderful Copenhagen

                              Detroit Tigers Spis treści Historia | Skład zespołu | Sukcesy | Członkowie Baseball Hall of Fame | Zastrzeżone numery | Przypisy | Menu nawigacyjneEncyclopedia of Detroit - Detroit TigersTigers Stadium, Detroit, MITigers Timeline 1900sDetroit Tigers Team History & EncyclopediaTigers Timeline 1910s1935 World Series1945 World Series1945 World Series1984 World SeriesComerica Park, Detroit, MI2006 World Series2012 World SeriesDetroit Tigers 40-Man RosterDetroit Tigers Coaching StaffTigers Hall of FamersTigers Retired Numberse