Overloading == for better readability I was working on a project recently that had a good amount of business logic associated with status codes.   To better understand the flow of logic in the domain layer, I created an enum representation of the statuses and overloaded the equality operator in the status domain model to check against the enum.  

Is this good practice, or does this an unnecessary abstraction?  Also seeing if I should implement the GetHashCode() and Equal() methods or perhaps just make them just return

() =&gt; throw new InvalidOperationException();


Implementation

public class StatusDm
{

    public StatusDm() { }
    public StatusDm(Models.Database.Status status)
    {
        Id = status.Id;
        Name = status.Name;
    }
    public int Id { get; set; }
    public string Name { get; set; }


    public void DatabaseTransfer(ref Models.Database.Status status)
    {
        status.Name = Name;
    }
    public static bool operator ==(StatusDm domainStatus, Models.Constants.StatusEnum status)
    {
        return domainStatus?.Id == (int)status;
    }

    public static bool operator !=(StatusDm domainStatus, Models.Constants.StatusEnum status)
    {
        return !(domainStatus?.Id == (int)status);
    }
}


Usage

if(individual.StatusModel == StatusEnum.Submitted || individual.StatusModel == StatusEnum.Disqualified)
{
    ...
}


Appreciate any feedback or critic. Thanks!

Edit:  There was a question in regards to how it would normally be done in this application.  Here was the evolution of the usage statement

First Implementation

if (storedIndividual.Status == (int)IndividualStatus.InProgress &amp;&amp;
    (individual.StatusModel.Id == (int)IndividualStatus.Submitted || 
        individual.StatusModel.Id == (int)IndividualStatus.Disqualified))

{
    SetFinishedIndividualFormValues(ref individual);
    if (individual.StatusModel.Id == (int)IndividualStatus.Submitted)
    {
        SendSubmittedFileEmail(individual);
    }
}
else if (individual.StatusModel.Id != (int)IndividualStatus.Disqualified)
{
    SendStatusChange(individual);
}


Revised Implementation

private void HandleStatusChanges(Models.Database.Individual storedIndividual, ref Models.Domain.IndividualDm individual)
{
    if (storedIndividual.Status == (int)IndividualStatus.InProgress &amp;&amp;
        (individual.Status == IndividualStatus.Submitted || 
            individual.Status == IndividualStatus.Disqualified))
    {
        SetFinishedIndividualFormValues(ref individual);
        if (individual.Status == IndividualStatus.Submitted)
        {
            SendSubmittedFileEmail(individual);
        }
    }
    else if (individual.Status != IndividualStatus.Disqualified)
    {
        SendStatusChange(individual);
    }
}
It is difficult to judge without full code, but while keeping things mutable (please use a more descriptive names, a future you will thank you):

public class StatusModel
{
    public IndividualStatus Status { get; set; }
    public int StatusId { get =&gt; (int)Status; set =&gt; Status = (IndividualStatus)value; }  
    public bool InProgressStatus =&gt; Status == IndividualStatus.InProgress;
    public bool SubmittedStatus =&gt; Status == IndividualStatus.Submitted;
    public bool DisqualifiedStatus =&gt; Status == IndividualStatus.Disqualified;
    public bool DisqualifiedOrSubmittedStatus =&gt; DisqualifiedStatus || SubmittedStatus;
    public bool JustFinished(StatusModel stored) =&gt;
          stored.InProgressStatus &amp;&amp; DisqualifiedOrSubmittedStatus;
    public bool JustSubmitted(StatusModel stored) =&gt;
        JustFinished(stored) &amp;&amp; SubmittedStatus;
    public bool StillInProgress(StatusModel stored) =&gt;
        !JustFinished(stored) &amp;&amp; !DisqualifiedStatus;
}


As a next step you could also define an implicit conversion operators from/to int/enum types and make this class immutable.

public class StatusModel
{
    public static implicit operator StatusModel(IndividualStatus status) =&gt; new StatusModel(status);
    public static implicit operator IndividualStatus(StatusModel model) =&gt; model.Status;
    public static implicit operator StatusModel(int id) =&gt; (IndividualStatus)id;
    public static implicit operator int(StatusModel model) =&gt; (int)model.Status;
    StatusModel(IndividualStatus status) =&gt; Status = status;
    public IndividualStatus Status { get; set; }
    public bool InProgressStatus =&gt; Status == IndividualStatus.InProgress;
    public bool SubmittedStatus =&gt; Status == IndividualStatus.Submitted;
    public bool DisqualifiedStatus =&gt; Status == IndividualStatus.Disqualified;
    public bool DisqualifiedOrSubmittedStatus =&gt; DisqualifiedStatus || SubmittedStatus;
    public bool JustFinished(StatusModel stored) =&gt;
          stored.InProgressStatus &amp;&amp; DisqualifiedOrSubmittedStatus;
    public bool JustSubmitted(StatusModel stored) =&gt;
        JustFinished(stored) &amp;&amp; SubmittedStatus;
    public bool StillInProgress(StatusModel stored) =&gt;
        !JustFinished(stored) &amp;&amp; !DisqualifiedStatus;
}


It is a bunch of code (C# is a ridiculously verbose language), but it would be very easy to have more logic here, adding anything status related would be a very cheap operation.

private void HandleStatusChanges(
    Models.Database.Individual storedIndividual, 
    ref Models.Domain.IndividualDm individual)
{
    if (individual.Status.JustFinished(storedIndividual.Status))
        SetFinishedIndividualFormValues(ref individual);
    if (individual.Status.JustSubmitted(storedIndividual.Status))
        SendSubmittedFileEmail(individual);
    if (individual.Status.StillInProgress(storedIndividual.Status))
        SendStatusChange(individual);
}


I would also define and associate custom JsonConverter and TypeConverter with StatusModel, so it will look like a status integer ID for asp.net (see an example here).

P.S. Generally speaking, data entity types should never be visible in the business core:
https://blog.cleancoder.com/uncle-bob/2016/01/04/ALittleArchitecture.html