0

I have some objects that I'd like to put into an associative container that groups them by a non-comparable field value. So if I had the following:

using System.Collections.Generic;
using Pair = System.Tuple<Penguin, int>;

class Penguin {}

class Whatever {

    public static void Main(string[] args) {
        Penguin emperor = new Penguin(),
                adelie = new Penguin(),
                batmanVillain = new Penguin();

        var okay = new HypotheticalCollection<Pair>(5);

        okay.Add(new Pair(emperor, 1) );
        okay.Add(new Pair(adelie, 2) );
        okay.Add(new Pair(batmanVillain, 3) );
        okay.Add(new Pair(emperor, -500) );
        okay.Add(new Pair(batmanVillain, 5) );

    }
}

and I iterated over the HypotheticalCollection, I would want to see the two emperor entries together and the two batmanVillain entries together, but I don't care which one's first. However, I would like to be able to look up an entry in logarithmic time.

If I were using C++, I would just sort the Penguins by their address, but I don't have that luxury in C#. Right now I'm handling it by assigning a serial number to each of the objects, but that feels kind of hacky, and I'd prefer not to have the extra space overhead. Is there a better way, maybe a ReferenceLessThan function or something?

  • Why not write a [comparer](https://stackoverflow.com/questions/14336416/using-icomparer-for-sorting)? Once you've created one, you can pass it into the SortedSet [constructor](https://msdn.microsoft.com/en-us/library/dd395024(v=vs.110).aspx). – ProgrammingLlama Nov 20 '17 at 06:43

1 Answers1

1

Option 1: (suggestion)

public static class Whatever
{
    class Penguin
    {
        private Guid id = Guid.NewGuid();       
        public Guid GetId() { return id; }
    }

    public static void Main(string[] args)
    {
        Penguin emperor = new Penguin(),
            adelie = new Penguin(),
            batmanVillain = new Penguin();

        var okay = new List<KeyValuePair<Penguin, int>>();
        okay.Add(new KeyValuePair<Penguin, int>(emperor, 1));
        okay.Add(new KeyValuePair<Penguin, int>(adelie, 2));
        okay.Add(new KeyValuePair<Penguin, int>(batmanVillain, 3));
        okay.Add(new KeyValuePair<Penguin, int>(emperor, -500));
        okay.Add(new KeyValuePair<Penguin, int>(batmanVillain, 5));

        okay.Sort((a, b) => a.Key.GetId().CompareTo(b.Key.GetId()));

        // Iterate 'okay'
    }
}

Option 2 is to use the object address in the sort compare function, which according to this is not a fix address and can be changed by the CLR. In addition, getting the address requires to build your app with unsafe flag. If you claim that option 1 feels "hacky", so csharaply option 2 is super "hacky". And a GUID is a 128-bit integer (16 bytes).

elirandav
  • 1,913
  • 19
  • 27