/// <summary>
        /// The <c>GetHostEntryAsync</c> method does a reverse lookup on the IP <paramref name="address"/>,
        /// and queries a DNS server for the IP addresses and aliases associated with the resolved hostname.
        /// <para>
        /// IP addresses found are returned in <see cref="IPHostEntry.AddressList"/>.
        /// <see cref="ResourceRecordType.CNAME"/> records are used to populate the <see cref="IPHostEntry.Aliases"/>.<br/>
        /// The <see cref="IPHostEntry.HostName"/> property will be set to the resolved hostname of the <paramref name="address"/>.
        /// </para>
        /// </summary>
        /// <example>
        /// The following code example uses the <see cref="GetHostEntryAsync(IDnsQuery, IPAddress)"/> method to resolve an IP address to an <see cref="IPHostEntry"/> instance.
        /// <code>
        /// <![CDATA[
        /// public static async Task PrintHostEntry(IPAddress address)
        /// {
        ///     var lookup = new LookupClient();
        ///     IPHostEntry hostEntry = await lookup.GetHostEntryAsync(address);
        ///     Console.WriteLine(hostEntry.HostName);
        ///     foreach (var ip in hostEntry.AddressList)
        ///     {
        ///         Console.WriteLine(ip);
        ///     }
        ///     foreach (var alias in hostEntry.Aliases)
        ///     {
        ///         Console.WriteLine(alias);
        ///     }
        /// }
        /// ]]>
        /// </code>
        /// </example>
        /// <remarks>
        /// The method has some logic to populate the <see cref="IPHostEntry.Aliases"/> list:
        /// <list type="bullet">
        /// <item>
        /// <term>
        /// In case of sub-domain queries or similar, there might be multiple <see cref="ResourceRecordType.CNAME"/> records for one <see cref="IPAddress"/>,
        /// </term>
        /// </item><item>
        /// <term>
        /// If only one <see cref="IPAddress"/> is in the result set, all the aliases found will be returned.
        /// </term>
        /// </item><item>
        /// <term>
        /// If more than one <see cref="IPAddress"/> is in the result set, aliases are returned only if at least one doesn't match the queried hostname.
        /// </term>
        /// </item>
        /// </list>
        /// </remarks>
        /// <param name="query">The <see cref="IDnsQuery"/> instance.</param>
        /// <param name="address">The <see cref="IPAddress"/> to query for.</param>
        /// <returns>
        /// An <see cref="IPHostEntry"/> instance that contains address information about the host specified in <paramref name="address"/>.
        /// In case the <paramref name="address"/> could not be resolved to a domain name, this method returns <c>null</c>,
        /// unless <see cref="ILookupClient.ThrowDnsErrors"/> is set to true, then it might throw a <see cref="DnsResponseException"/>.
        /// </returns>
        /// <exception cref="ArgumentNullException">If <paramref name="address"/> is null.</exception>
        /// <exception cref="DnsResponseException">In case <see cref="ILookupClient.ThrowDnsErrors"/> is set to true and a DNS error occurs.</exception>
        public static async Task <IPHostEntry> GetHostEntryAsync(this IDnsQuery query, IPAddress address)
        {
            if (query == null)
            {
                throw new ArgumentNullException(nameof(query));
            }
            if (address == null)
            {
                throw new ArgumentNullException(nameof(address));
            }

            var hostName = await query.GetHostNameAsync(address).ConfigureAwait(false);

            if (string.IsNullOrWhiteSpace(hostName))
            {
                return(null);
            }

            return(await GetHostEntryFromNameAsync(query, hostName).ConfigureAwait(false));
        }