/// <summary>
        /// The <c>GetHostEntryAsync</c> method queries a DNS server for the IP addresses and aliases associated with the <paramref name="hostNameOrAddress"/>.
        /// In case <paramref name="hostNameOrAddress"/> is an <see cref="IPAddress"/>, <c>GetHostEntry</c> does a reverse lookup on that first to determine the 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 or <paramref name="hostNameOrAddress"/>.
        /// </para>
        /// </summary>
        /// <example>
        /// The following code example uses the <see cref="GetHostEntryAsync(IDnsQuery, string)"/> method to resolve an IP address or hostname to an <see cref="IPHostEntry"/> instance.
        /// <code>
        /// <![CDATA[
        /// public static async Task PrintHostEntry(string hostOrIp)
        /// {
        ///     var lookup = new LookupClient();
        ///     IPHostEntry hostEntry = await lookup.GetHostEntryAsync(hostOrIp);
        ///     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="hostNameOrAddress">The <see cref="IPAddress"/> or host name to query for.</param>
        /// <returns>
        /// An <see cref="IPHostEntry"/> instance that contains address information about the host specified in <paramref name="hostNameOrAddress"/>.
        /// In case the <paramref name="hostNameOrAddress"/> 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="hostNameOrAddress"/> is null.</exception>
        /// <exception cref="DnsResponseException">In case <see cref="ILookupClient.ThrowDnsErrors"/> is set to true and a DNS error occurs.</exception>
        public static Task <IPHostEntry> GetHostEntryAsync(this IDnsQuery query, string hostNameOrAddress)
        {
            if (query == null)
            {
                throw new ArgumentNullException(nameof(query));
            }
            if (string.IsNullOrWhiteSpace(hostNameOrAddress))
            {
                throw new ArgumentNullException(nameof(hostNameOrAddress));
            }

            if (IPAddress.TryParse(hostNameOrAddress, out IPAddress address))
            {
                return(query.GetHostEntryAsync(address));
            }

            return(GetHostEntryFromNameAsync(query, hostNameOrAddress));
        }