Dictionary Using Hash Of Object

My program allows the server to send a module to a client, and the client will a respond back with module information after it has loaded it. The server store stores the client information in a List called ‘loadingModules’. When the server receives that response from the client, it will remove the information from said list to indicate the load operation has completed for that module.

The problem here is is the way I’m currently doing it is by looping through the entire list and checking if two members are equal (ModuleName, and TimeStamp). This is not only just inefficient, but also makes the code look terrible. I am wondering if there is some way to do it using a hash of those two members to access the modules in perhaps a dictionary instead of what I am currently doing.

public List<ClientModule> LoadingClientModules = new();
public List<ClientModule> LoadedClientModules = new();

private void ClientModuleAdded_Callback(Packet packet)
{
    ClientModule f = Utils.ByteArrayToStructure<ClientModule>(packet.Payload, 0);
    Utils.Log.Information($"{_ClientInformation.ComputerUser} Loaded  {f.ModuleName} TimeDateStamp: {f.TimeDateStamp} Address: {f.Address}");
    LoadedClientModules.Add(f);

    LoadingClientModules.RemoveAll(i => i.ModuleName == f.ModuleName && i.TimeDateStamp == f.TimeDateStamp);

    OnClientModuleLoaded?.Invoke(this, f);
}

>Solution :

You could provide a custom IEqualityComparter<ClientModule> that compares these 2 properties. Then you can use that for a Dictionary or – better here – a HashSet<ClientModule>:

public HashSet<ClientModule> LoadingClientModules = new(new ClientModuleComparer());
public HashSet<ClientModule> LoadedClientModules = new(new ClientModuleComparer());

private void ClientModuleAdded_Callback(Packet packet)
{
    ClientModule f = Utils.ByteArrayToStructure<ClientModule>(packet.Payload, 0);
    LoadedClientModules.Add(f);
    LoadingClientModules.Remove(f);
}

Here’s a possible implementation:

public class ClientModuleComparer : IEqualityComparer<ClientModule>
{
    public bool Equals(ClientModule? x, ClientModule? y)
    {
        if (x == null && y == null) return true;
        if (x == null || y == null) return false;
        return x.ModuleName == y.ModuleName && y.TimeDateStamp == y.TimeDateStamp;
    }

    public int GetHashCode([DisallowNull] ClientModule obj)
    {
        if (obj == null) return 0;
        unchecked // Overflow is fine, just wrap
        {
            int hash = 17;
            // Suitable nullity checks etc, of course :)
            hash = hash * 23 + obj.ModuleName.GetHashCode();
            hash = hash * 23 + obj.TimeDateStamp.GetHashCode();
            return hash;
        }
    }
}

Leave a Reply