public NormalizedEmailAddress(string local, EmailDomainName domain)
        {
            if (string.IsNullOrWhiteSpace(local))
            {
                throw new ArgumentEmptyException(nameof(local));
            }
            if (domain == null)
            {
                throw new ArgumentNullException(nameof(domain));
            }

            Local  = local;
            Domain = domain;
        }
        /// <summary>
        /// Merges emails from a range of domain names into a single domain. Useful
        /// if an email provider has multiple email domains that map to the same mailboxs
        /// e.g. addresses for both "gmail.com" and "googlemail.com" map to the same inbox
        /// so these can be merged into one for the purposes of uniqueness checks.
        /// </summary>
        /// <param name="primaryDomain">
        /// The domain name to replace any <paramref name="otherDomains"/>
        /// with e.g. "gmail.com".
        /// </param>
        /// <param name="otherDomains">
        /// A set of domain names to check e.g. to check for a gmail domain
        /// you'd need to pass <c>["googlemail.com"]</c>.
        /// </param>
        /// <returns>Returns a new <see cref="NormalizedEmailAddress"/> instance reflecting any changes.</returns>
        public NormalizedEmailAddress MergeDomains(string primaryDomain, params string[] otherDomains)
        {
            if (HasDomain(otherDomains))
            {
                var domain = EmailDomainName.Parse(primaryDomain);
                if (domain == null)
                {
                    throw new InvalidOperationException($"Domain name {primaryDomain} could not be parsed.");
                }
                return(new NormalizedEmailAddress(Local, domain));
            }

            return(this);
        }
        /// <summary>
        /// Applies the <paramref name="modifier"/> function to the domain part of the email address.
        /// </summary>
        /// <param name="modifier">
        /// Function to modify the domain name part of the email address. This function passes in the
        /// existing domain name and expects a modified version to be returned.
        /// </param>
        /// <returns>Returns a new <see cref="NormalizedEmailAddress"/> instance reflecting any changes.</returns>
        public NormalizedEmailAddress AlterDomain(Func <string, string> modifier)
        {
            if (modifier == null)
            {
                throw new ArgumentNullException(nameof(modifier));
            }
            var newDomainName = modifier(Domain.Name);
            var newDomain     = EmailDomainName.Parse(newDomainName);

            if (newDomain == null)
            {
                throw new InvalidOperationException($"Domain name {newDomain} could not be parsed.");
            }

            return(new NormalizedEmailAddress(
                       Local,
                       newDomain
                       ));
        }