Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impement IEquatable on EmailAddress to Filter Duplicates #425

Closed
NuNn-DaDdY opened this issue Mar 22, 2017 · 2 comments · Fixed by #905
Closed

Impement IEquatable on EmailAddress to Filter Duplicates #425

NuNn-DaDdY opened this issue Mar 22, 2017 · 2 comments · Fixed by #905
Labels
difficulty: medium fix is medium in difficulty type: community enhancement feature request not on Twilio's roadmap

Comments

@NuNn-DaDdY
Copy link

NuNn-DaDdY commented Mar 22, 2017

Issue Summary

By implementing IEquatable on EmailAddress you'd be able to filter out duplicate emails when calling methods such as AddTo(s), AddCC(s), and AddBCC(s).

IEquatable Implementation

public class EmailAddress : IEquatable<EmailAddress>
{
	public EmailAddress()
	{
	}

	public EmailAddress(string email, string name = null)
	{
		this.Email = email;
		this.Name = name;
	}

	[JsonProperty(PropertyName = "name")]
	public string Name { get; set; }

	[JsonProperty(PropertyName = "email")]
	public string Email { get; set; }

	public bool Equals(EmailAddress other)
	{
		if (other == null) 
		{
			return false;
		}			
		return (this.Email == other.Email);
	}
	
	public override bool Equals(Object obj)
	{
		if (obj == null)
		{
			return false;
		}
		var email = obj as EmailAddress;
		return Equals(email);
	}
	
	public override int GetHashCode()
	{
		return this.Email.GetHashCode();
	}
	
	public static bool operator == (Email emailOne, Email emailTwo)
	{
		if (((object)emailOne) == null || ((object)emailTwo) == null)
		{
			return Object.Equals(emailOne, emailTwo);
		}
		return emailOne.Equals(emailTwo);
	}
	
	public static bool operator != (Email emailOne, Email emailTwo)
	{
		if (((object)emailOne) == null || ((object)emailTwo) == null)
		{
			return !Object.Equals(emailOne, emailTwo);
		}
		return !emailOne.Equals(emailTwo);
	}
}

Sample: SendGridMessage.AddTo() Taking Advantage of the IEquatable

public void AddTos(List<EmailAddress> emails, int personalizationIndex = 0, Personalization personalization = null)
{
	if (personalization != null)
	{
                // Using Union in place of AddRange
		personalization.Tos.Union(emails);
		if (this.Personalizations == null)
		{
			this.Personalizations = new List<Personalization>();
			this.Personalizations.Add(personalization);
		}
		else
		{
			this.Personalizations.Add(personalization);
		}

		return;
	}

	if (this.Personalizations != null)
	{
		if ((personalizationIndex != 0) && (this.Personalizations.Count() <= personalizationIndex))
		{
			var p = new Personalization();
			this.Personalizations.Insert(personalizationIndex, p);
		}

		if (this.Personalizations[personalizationIndex].Tos == null)
		{
			this.Personalizations[personalizationIndex].Tos = new List<EmailAddress>();
		}

                // Using Union in place of AddRange
		this.Personalizations[personalizationIndex].Tos.Union(emails));
		return;
	}

	this.Personalizations = new List<Personalization>()
	{
		new Personalization()
		{
                        // Get rid of any duplicates with Distinct
			Tos = emails.Distinct()
		}
	};
	return;
}

Technical details:

  • sendgrid-csharp Version: master (latest commit: [commit number])
  • .NET Version: 4.6.1
@ottomatic
Copy link
Contributor

ottomatic commented Mar 23, 2017

Good suggestion.

But then the comparisons should really be case insensitive. So instead of

return (this.Email == other.Email);

It should be:

return (this.Email.ToLower() == other.Email.ToLower());

And instead of:
return this.Email.GetHashCode();

It should be:
return this.Email.ToLower().GetHashCode();

The code assume that the Email property is always non-null. Perhaps that is not always the case, so null checks will need to be inserted in a few places?

@NuNn-DaDdY
Copy link
Author

NuNn-DaDdY commented Mar 23, 2017

I agree with the case insensitive comparisons and with the non-null check(s). I overlooked the Email property having a public setter so the Equals(EmailAddress other) and GetHashCode would want to check for null. A null/empty check could also be added to the constructor when the email and name are passed in:

public EmailAddress(string email, string name = null)
{
	if (string.IsNullOrWhiteSpace(email))
	{
		throw new ArgumentException(nameof(email));
	}
	this.Email = email.Trim();	
	this.Name = (string.IsNullOrWhiteSpace(name)) ? null : name.Trim();
}

@thinkingserious thinkingserious added status: help wanted requesting help from the community type: community enhancement feature request not on Twilio's roadmap labels Mar 23, 2017
@thinkingserious thinkingserious added difficulty: medium fix is medium in difficulty hacktoberfest labels Sep 30, 2017
Kevek added a commit to Kevek/sendgrid-csharp that referenced this issue Oct 3, 2017
@thinkingserious thinkingserious added status: work in progress Twilio or the community is in the process of implementing and removed status: help wanted requesting help from the community labels Mar 1, 2018
@childish-sambino childish-sambino removed the status: work in progress Twilio or the community is in the process of implementing label Apr 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
difficulty: medium fix is medium in difficulty type: community enhancement feature request not on Twilio's roadmap
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants