I made some modifications

Jan 24, 2009 at 2:33 AM
I made some modifications :
1. Changed the list type to List instead of IList.
2. replaced the lookup query to List.Find() instead of linq query.
3. converted the method "GetIPv4Data" and the class "IPv4Data" to public.
4. some small code modifications (not logic).

I have a little problem with this code logic:
GetIPv4Data is private and called from every single extension method, but what if i want to display Iso3166TwoLetterCode and Iso3166ThreeLetterCode and the Country name, this code will create the ip lookup 3 times.
In order to avoid it, I see no choice but converting the method "GetIPv4Data" and the class "IPv4Data" to public and return the IPv4Data instance if needed.

my code:

<!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset177\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red128\green128\blue128;\red0\green128\blue0;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf1 namespace\cf0 WorldDomination.Net\par ??\{\par ??\par ?? \cf1 using\cf0 System;\par ?? \cf1 using\cf0 System.Collections.Generic;\par ?? \cf1 using\cf0 System.IO;\par ?? \cf1 using\cf0 System.IO.Compression;\par ?? \cf1 using\cf0 System.Net;\par ?? \cf1 using\cf0 System.Reflection;\par ??\par ??\par ??\par ?? \cf4 ///\cf5 \cf4 <summary>\par ??\cf0 \cf4 ///\cf5 Extension methods for the IPAddress class.\par ??\cf0 \cf4 ///\cf5 \cf4 </summary>\par ??\cf0 \cf1 public\cf0 \cf1 static\cf0 \cf1 class\cf0 \cf6 IPAddressExtensions\par ??\cf0 \{\par ??\cf1 #region\cf0 Fields\par ??\par ?? \cf1 private\cf0 \cf1 static\cf0 \cf6 List\cf0 <\cf6 IPv4Data\cf0 > _geoIpDataList;\par ?? \cf1 private\cf0 \cf1 static\cf0 \cf1 readonly\cf0 \cf1 object\cf0 _syncObject = \cf1 new\cf0 \cf1 object\cf0 ();\par ??\par ??\cf1 #endregion\par ??\par ?? #region\cf0 Properties\par ??\par ?? \cf1 private\cf0 \cf1 static\cf0 \cf6 List\cf0 <\cf6 IPv4Data\cf0 > GeoIpDataList\par ?? \{\par ?? \cf1 get\par ??\cf0 \{\par ?? \cf1 if\cf0 (_geoIpDataList == \cf1 null\cf0 )\par ?? \{\par ?? \cf1 lock\cf0 (_syncObject)\par ?? \{\par ?? \cf1 if\cf0 (_geoIpDataList == \cf1 null\cf0 )\par ?? \{\par ?? _geoIpDataList = ReadInCSVFile();\par ?? \}\par ?? \}\par ?? \}\par ??\par ?? \cf1 return\cf0 _geoIpDataList;\par ?? \}\par ?? \}\par ??\par ?? \cf4 ///\cf5 \cf4 <summary>\par ??\cf0 \cf4 ///\cf5 The Regional Internet Registery.\par ??\cf0 \cf4 ///\cf5 \cf4 </summary>\par ??\cf0 \cf4 ///\cf5 \cf4 <remarks>\cf5 What the hell is this? Wiki knows all :- http://en.wikipedia.org/wiki/Regional_Internet_Registry/\cf4 <br /><br />\par ??\cf0 \cf4 ///\cf5 Expected values are: Reserved, IANA, IETF, APCNIC, ARIN, LACNIC, RIPENCC and AFRINIC.\cf4 </remarks>\par ??\cf0 \cf4 ///\cf5 \cf4 <returns>\cf5 The RIR code.\cf4 </returns>\par ??\cf0 \cf1 public\cf0 \cf1 static\cf0 \cf1 string\cf0 Registry(\cf1 this\cf0 \cf6 IPAddress\cf0 ipAddress)\par ?? \{\par ?? \cf6 IPv4Data\cf0 ipv4Data = GetIPv4Data(ipAddress);\par ?? \cf1 return\cf0 ipv4Data == \cf1 null\cf0 ? \cf1 null\cf0 : ipv4Data.Registry;\par ?? \}\par ??\par ?? \cf4 ///\cf5 \cf4 <summary>\par ??\cf0 \cf4 ///\cf5 The date this IP or block was assigned.\par ??\cf0 \cf4 ///\cf5 \cf4 </summary>\par ??\cf0 \cf4 ///\cf5 \cf4 <remarks>\cf5 If the date was unknown when assigned, a null value is returned.\cf4 </remarks>\par ??\cf0 \cf4 ///\cf5 \cf4 <returns>\cf5 The date and time in UTC if known, otherwise null.\cf4 </returns>\par ??\cf0 \cf1 public\cf0 \cf1 static\cf0 \cf6 DateTimeOffset\cf0 ? AssignedDateTime(\cf1 this\cf0 \cf6 IPAddress\cf0 ipAddress)\par ?? \{\par ?? \cf6 IPv4Data\cf0 ipv4Data = GetIPv4Data(ipAddress);\par ?? \cf1 if\cf0 (ipv4Data == \cf1 null\cf0 )\par ?? \cf1 return\cf0 \cf1 null\cf0 ;\par ?? \par ?? \par ?? \cf1 return\cf0 \cf1 new\cf0 \cf6 DateTimeOffset\cf0 (1970,\par ?? 1,\par ?? 1,\par ?? 0,\par ?? 0,\par ?? 0,\par ?? 0,\par ?? \cf1 new\cf0 \cf6 TimeSpan\cf0 (0, 0, 0)).AddSeconds(ipv4Data.Assigned);\par ?? \par ?? \}\par ??\par ?? \cf4 ///\cf5 \cf4 <summary>\par ??\cf0 \cf4 ///\cf5 The two letter ISO 3166 code.\par ??\cf0 \cf4 ///\cf5 \cf4 </summary>\par ??\cf0 \cf4 ///\cf5 \cf4 <remarks>\cf5 What the hell is this? Wiki knows all :- http://en.wikipedia.org/wiki/ISO_3166/\cf4 </remarks>\par ??\cf0 \cf4 ///\cf5 \cf4 <returns>\cf5 The two letter code.\cf4 </returns>\par ??\cf0 \cf1 public\cf0 \cf1 static\cf0 \cf1 string\cf0 Iso3166TwoLetterCode(\cf1 this\cf0 \cf6 IPAddress\cf0 ipAddress)\par ?? \{\par ?? \cf6 IPv4Data\cf0 ipv4Data = GetIPv4Data(ipAddress);\par ?? \cf1 return\cf0 ipv4Data == \cf1 null\cf0 ? \cf1 null\cf0 : ipv4Data.Iso3166TwoLetterCode;\par ?? \}\par ??\par ?? \cf4 ///\cf5 \cf4 <summary>\par ??\cf0 \cf4 ///\cf5 The three letter ISO 3166 code.\par ??\cf0 \cf4 ///\cf5 \cf4 </summary>\par ??\cf0 \cf4 ///\cf5 \cf4 <remarks>\cf5 What the hell is this? Wiki knows all :- http://en.wikipedia.org/wiki/ISO_3166/\cf4 </remarks>\par ??\cf0 \cf4 ///\cf5 \cf4 <param name="ipAddress"></param>\par ??\cf0 \cf4 ///\cf5 \cf4 <returns>\cf5 The three letter code.\cf4 </returns>\par ??\cf0 \cf1 public\cf0 \cf1 static\cf0 \cf1 string\cf0 Iso3166ThreeLetterCode(\cf1 this\cf0 \cf6 IPAddress\cf0 ipAddress)\par ?? \{\par ?? \cf6 IPv4Data\cf0 ipv4Data = GetIPv4Data(ipAddress);\par ?? \cf1 return\cf0 ipv4Data == \cf1 null\cf0 ? \cf1 null\cf0 : ipv4Data.Iso3166ThreeLetterCode;\par ?? \}\par ??\par ?? \cf4 ///\cf5 \cf4 <summary>\par ??\cf0 \cf4 ///\cf5 The full country name.\par ??\cf0 \cf4 ///\cf5 \cf4 </summary>\par ??\cf0 \cf4 ///\cf5 \cf4 <returns>\cf5 The full country name.\cf4 </returns>\par ??\cf0 \cf1 public\cf0 \cf1 static\cf0 \cf1 string\cf0 Country(\cf1 this\cf0 \cf6 IPAddress\cf0 ipAddress)\par ?? \{\par ?? \cf6 IPv4Data\cf0 ipv4Data = GetIPv4Data(ipAddress);\par ?? \cf1 return\cf0 ipv4Data == \cf1 null\cf0 ? \cf1 null\cf0 : ipv4Data.Country;\par ?? \}\par ??\par ??\cf1 #endregion\par ??\par ?? #region\cf0 Methods\par ??\par ??\par ?? \cf4 ///\cf5 \cf4 <summary>\par ??\cf0 \cf4 ///\cf5 Gets the I PV4 data.\par ??\cf0 \cf4 ///\cf5 \cf4 </summary>\par ??\cf0 \cf4 ///\cf5 \cf4 <param name="ipAddress">\cf5 The ip address.\cf4 </param>\par ??\cf0 \cf4 ///\cf5 \cf4 <returns></returns>\par ??\cf0 \cf4 ///\cf5 \cf4 <exception cref="ArgumentNullException"><c>\cf5 ipAddress\cf4 </c>\cf5 is null.\cf4 </exception>\par ??\cf0 \cf4 ///\cf5 \cf4 <exception cref="ArgumentException">\cf5 Only Internet Protocol version 4 (IPv4) addresses are accepted.\cf4 </exception>\par ??\cf0 \cf4 ///\cf5 \cf4 <exception cref="InvalidOperationException">\cf5 Internet Protocol (IPv4) address list was not successfully loaded into memory. Unable to process your request.\cf4 </exception>\par ??\cf0 \cf1 public\cf0 \cf1 static\cf0 \cf6 IPv4Data\cf0 GetIPv4Data(\cf6 IPAddress\cf0 ipAddress)\par ?? \{\par ?? \cf1 if\cf0 (ipAddress == \cf1 null\cf0 )\par ?? \{\par ?? \cf1 throw\cf0 \cf1 new\cf0 \cf6 ArgumentNullException\cf0 (\cf7 "ipAddress"\cf0 );\par ?? \}\par ?? \par ?? \cf1 if\cf0 (ipAddress.AddressFamily != System.Net.Sockets.\cf6 AddressFamily\cf0 .InterNetwork)\par ?? \{\par ?? \cf1 throw\cf0 \cf1 new\cf0 \cf6 ArgumentException\cf0 (\cf7 "Only Internet Protocol version 4 (IPv4) addresses are accepted."\cf0 );\par ?? \}\par ??\par ?? \cf1 if\cf0 (GeoIpDataList == \cf1 null\cf0 )\par ?? \{\par ?? \cf1 throw\cf0 \cf1 new\cf0 \cf6 InvalidOperationException\cf0 (\cf7 "Internet Protocol (IPv4) address list was not successfully loaded into memory. Unable to process your request."\cf0 );\par ?? \}\par ??\par ?? \cf1 byte\cf0 [] ipAddressBytes = ipAddress.GetAddressBytes();\par ?? \cf1 long\cf0 ipAddressLong = (\cf1 long\cf0 )ipAddressBytes[3] +\par ?? (ipAddressBytes[2] * 256L) +\par ?? (ipAddressBytes[1] * 256L * 256L) +\par ?? (ipAddressBytes[0] * 256L * 256L * 256L);\par ??\par ?? \cf6 IPv4Data\cf0 ipv4Data = GeoIpDataList.Find(d => d.IpFrom <= ipAddressLong && d.IpTo >= ipAddressLong);\par ?? \cf5 /*\par ?? // Now retrieve the country specific data.\par ?? IPv4Data ipv4Data = (from d in GeoIpDataList\par ?? where d.IpFrom <= ipAddressLong && d.IpTo >= ipAddressLong\par ?? select d).SingleOrDefault();\par ?? */\par ??\cf0 \cf1 return\cf0 ipv4Data;\par ?? \}\par ??\par ?? \cf1 private\cf0 \cf1 static\cf0 \cf6 List\cf0 <\cf6 IPv4Data\cf0 > ReadInCSVFile()\par ?? \{\par ?? \cf1 string\cf0 row;\par ?? \cf6 List\cf0 <\cf6 IPv4Data\cf0 > ipv4DataList = \cf1 null\cf0 ;\par ?? \par ??\par ??\par ?? \cf5 // First, decompress the gzipped data file.\par ??\cf0 \cf6 Assembly\cf0 assembly = \cf6 Assembly\cf0 .GetExecutingAssembly();\par ??\par ?? \cf1 using\cf0 (\cf6 GZipStream\cf0 gzipStream = \cf1 new\cf0 \cf6 GZipStream\cf0 (assembly.GetManifestResourceStream(\cf7 "WorldDomination.Net.IpToCountry.csv.gz"\cf0 ),\par ?? \cf6 CompressionMode\cf0 .Decompress))\par ?? \{\par ?? \cf1 using\cf0 (\cf6 TextReader\cf0 textReader = \cf1 new\cf0 \cf6 StreamReader\cf0 (gzipStream))\par ?? \{\par ?? \cf1 while\cf0 ((row = textReader.ReadLine()) != \cf1 null\cf0 )\par ?? \{\par ?? \cf1 if\cf0 (!\cf1 string\cf0 .IsNullOrEmpty(row) &&\par ?? !row.StartsWith(\cf7 "#"\cf0 ,\par ?? \cf6 StringComparison\cf0 .OrdinalIgnoreCase))\par ?? \{\par ??\par ?? \cf1 long\cf0 ipFrom;\par ?? \cf1 long\cf0 ipTo;\par ?? \cf1 long\cf0 assigned;\par ??\par ?? \cf5 // We have a row, so lets split it then add it to our collection.\par ??\cf0 \cf1 string\cf0 [] rowArray = row.Replace(\cf7 "\\""\cf0 , \cf1 string\cf0 .Empty).Split(\cf7 ','\cf0 );\par ?? \cf1 if\cf0 (rowArray.Length == 7 &&\par ?? \cf1 long\cf0 .TryParse(rowArray[0], \cf1 out\cf0 ipFrom) &&\par ?? \cf1 long\cf0 .TryParse(rowArray[1], \cf1 out\cf0 ipTo) &&\par ?? \cf1 long\cf0 .TryParse(rowArray[3], \cf1 out\cf0 assigned))\par ?? \{\par ?? \cf5 // We have a legit row, so lets add this to our collection.\par ??\cf0 \cf1 if\cf0 (ipv4DataList == \cf1 null\cf0 )\par ?? \{\par ?? ipv4DataList = \cf1 new\cf0 \cf6 List\cf0 <\cf6 IPv4Data\cf0 >();\par ?? \}\par ??\par ?? ipv4DataList.Add(\cf1 new\cf0 \cf6 IPv4Data\par ??\cf0 \{\par ?? IpFrom = ipFrom,\par ?? IpTo = ipTo,\par ?? Registry = rowArray[2],\par ?? Assigned = assigned,\par ?? Iso3166TwoLetterCode = rowArray[4],\par ?? Iso3166ThreeLetterCode = rowArray[5],\par ?? Country = rowArray[6]\par ?? \});\par ?? \}\par ?? \}\par ?? \}\par ?? \}\par ?? \}\par ??\par ?? \cf1 return\cf0 ipv4DataList == \cf1 null\cf0 ||\par ?? ipv4DataList.Count <= 0 ? \cf1 null\cf0 : ipv4DataList;\par ?? \}\par ??\par ??\cf1 #endregion\par ??\cf0 \}\par ??\}} -->
namespace WorldDomination.Net
{
 
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.IO.Compression;
    using System.Net;
    using System.Reflection;
 
 
 
    /// <summary>
    /// Extension methods for the IPAddress class.
    /// </summary>
    public static class IPAddressExtensions
    {
        #region Fields
 
        private static List<IPv4Data> _geoIpDataList;
        private static readonly object _syncObject = new object();
 
        #endregion
 
        #region Properties
 
        private static List<IPv4Data> GeoIpDataList
        {
            get
            {
                if (_geoIpDataList == null)
                {
                    lock (_syncObject)
                    {
                        if (_geoIpDataList == null)
                        {
                            _geoIpDataList = ReadInCSVFile();
                        }
                    }
                }
 
                return _geoIpDataList;
            }
        }
 
        /// <summary>
        /// The Regional Internet Registery.
        /// </summary>
        /// <remarks>What the hell is this? Wiki knows all :- http://en.wikipedia.org/wiki/Regional_Internet_Registry/<br /><br />
        /// Expected values are: Reserved, IANA, IETF, APCNIC, ARIN, LACNIC, RIPENCC and AFRINIC.</remarks>
        /// <returns>The RIR code.</returns>
        public static string Registry(this IPAddress ipAddress)
        {
            IPv4Data ipv4Data = GetIPv4Data(ipAddress);
            return ipv4Data == null ? null : ipv4Data.Registry;
        }
 
        /// <summary>
        /// The date this IP or block was assigned.
        /// </summary>
        /// <remarks>If the date was unknown when assigned, a null value is returned.</remarks>
        /// <returns>The date and time in UTC if known, otherwise null.</returns>
        public static DateTimeOffset? AssignedDateTime(this IPAddress ipAddress)
        {
            IPv4Data ipv4Data = GetIPv4Data(ipAddress);
            if (ipv4Data == null)
                return null;
 
 
            return new DateTimeOffset(1970,
            1,
            1,
            0,
            0,
            0,
            0,
            new TimeSpan(0, 0, 0)).AddSeconds(ipv4Data.Assigned);
 
        }
 
        /// <summary>
        /// The two letter ISO 3166 code.
        /// </summary>
        /// <remarks>What the hell is this? Wiki knows all :- http://en.wikipedia.org/wiki/ISO_3166/</remarks>
        /// <returns>The two letter code.</returns>
        public static string Iso3166TwoLetterCode(this IPAddress ipAddress)
        {
            IPv4Data ipv4Data = GetIPv4Data(ipAddress);
            return ipv4Data == null ? null : ipv4Data.Iso3166TwoLetterCode;
        }
 
        /// <summary>
        /// The three letter ISO 3166 code.
        /// </summary>
        /// <remarks>What the hell is this? Wiki knows all :- http://en.wikipedia.org/wiki/ISO_3166/</remarks>
        /// <param name="ipAddress"></param>
        /// <returns>The three letter code.</returns>
        public static string Iso3166ThreeLetterCode(this IPAddress ipAddress)
        {
            IPv4Data ipv4Data = GetIPv4Data(ipAddress);
            return ipv4Data == null ? null : ipv4Data.Iso3166ThreeLetterCode;
        }
 
        /// <summary>
        /// The full country name.
        /// </summary>
        /// <returns>The full country name.</returns>
        public static string Country(this IPAddress ipAddress)
        {
            IPv4Data ipv4Data = GetIPv4Data(ipAddress);
            return ipv4Data == null ? null : ipv4Data.Country;
        }
 
        #endregion
 
        #region Methods
 
 
        /// <summary>
        /// Gets the I PV4 data.
        /// </summary>
        /// <param name="ipAddress">The ip address.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"><c>ipAddress</c> is null.</exception>
        /// <exception cref="ArgumentException">Only Internet Protocol version 4 (IPv4) addresses are accepted.</exception>
        /// <exception cref="InvalidOperationException">Internet Protocol (IPv4) address list was not successfully loaded into memory. Unable to process your request.</exception>
        public static IPv4Data GetIPv4Data(IPAddress ipAddress)
        {
            if (ipAddress == null)
            {
                throw new ArgumentNullException("ipAddress");
            }
 
            if (ipAddress.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
            {
                throw new ArgumentException("Only Internet Protocol version 4 (IPv4) addresses are accepted.");
            }
 
            if (GeoIpDataList == null)
            {
                throw new InvalidOperationException("Internet Protocol (IPv4) address list was not successfully loaded into memory. Unable to process your request.");
            }
 
            byte[] ipAddressBytes = ipAddress.GetAddressBytes();
            long ipAddressLong = (long)ipAddressBytes[3] +
                                 (ipAddressBytes[2] * 256L) +
                                 (ipAddressBytes[1] * 256L * 256L) +
                                 (ipAddressBytes[0] * 256L * 256L * 256L);
 
            IPv4Data ipv4Data = GeoIpDataList.Find(d => d.IpFrom <= ipAddressLong && d.IpTo >= ipAddressLong);
            /*
            // Now retrieve the country specific data.
            IPv4Data ipv4Data = (from d in GeoIpDataList
                                 where d.IpFrom <= ipAddressLong && d.IpTo >= ipAddressLong
                                 select d).SingleOrDefault();
           */
            return ipv4Data;
        }
 
        private static List<IPv4Data> ReadInCSVFile()
        {
            string row;
            List<IPv4Data> ipv4DataList = null;
 
 
 
            // First, decompress the gzipped data file.
            Assembly assembly = Assembly.GetExecutingAssembly();
 
            using (GZipStream gzipStream = new GZipStream(assembly.GetManifestResourceStream("WorldDomination.Net.IpToCountry.csv.gz"),
                CompressionMode.Decompress))
            {
                using (TextReader textReader = new StreamReader(gzipStream))
                {
                    while ((row = textReader.ReadLine()) != null)
                    {
                        if (!string.IsNullOrEmpty(row) &&
                            !row.StartsWith("#",
                            StringComparison.OrdinalIgnoreCase))
                        {
 
                            long ipFrom;
                            long ipTo;
                            long assigned;
 
                            // We have a row, so lets split it then add it to our collection.
                            string[] rowArray = row.Replace("\"", string.Empty).Split(',');
                            if (rowArray.Length == 7 &&
                                long.TryParse(rowArray[0], out ipFrom) &&
                                long.TryParse(rowArray[1], out ipTo) &&
                                long.TryParse(rowArray[3], out assigned))
                            {
                                // We have a legit row, so lets add this to our collection.
                                if (ipv4DataList == null)
                                {
                                    ipv4DataList = new List<IPv4Data>();
                                }
 
                                ipv4DataList.Add(new IPv4Data
                                {
                                    IpFrom = ipFrom,
                                    IpTo = ipTo,
                                    Registry = rowArray[2],
                                    Assigned = assigned,
                                    Iso3166TwoLetterCode = rowArray[4],
                                    Iso3166ThreeLetterCode = rowArray[5],
                                    Country = rowArray[6]
                                });
                            }
                        }
                    }
                }
            }
 
            return ipv4DataList == null ||
                ipv4DataList.Count <= 0 ? null : ipv4DataList;
        }
 
        #endregion
    }
}


My performance test:

<!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset177\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red43\green145\blue175;\red163\green21\blue21;\red0\green128\blue0;}??\fs20 \par ??\par ??\cf1 namespace\cf0 Client\par ??\{\par ??\par ??\par ?? \cf1 using\cf0 System;\par ?? \cf1 using\cf0 System.Diagnostics;\par ?? \cf1 using\cf0 System.Net;\par ?? \cf1 using\cf0 WorldDomination.Net;\par ??\par ?? \cf1 class\cf0 \cf4 Program\par ??\cf0 \{\par ??\par ??\par ?? \cf1 const\cf0 \cf1 int\cf0 Iterations = 1000;\par ?? \cf1 static\cf0 \cf1 void\cf0 Main(\cf1 string\cf0 [] args)\par ?? \{\par ??\par ?? \cf1 string\cf0 ip = \cf5 "65.55.11.218"\cf0 ; \cf6 //US\par ??\cf0 \par ?? MeasureFormatTime(\cf5 "GetCountryInfo"\cf0 , () => GetCountryInfo(ip));\par ?? \cf4 Console\cf0 .ReadLine();\par ?? \}\par ??\par ?? \cf1 static\cf0 \cf1 void\cf0 MeasureFormatTime(\cf1 string\cf0 name, \cf4 Action\cf0 action)\par ?? \{\par ?? \cf1 var\cf0 stopwatch = \cf1 new\cf0 \cf4 Stopwatch\cf0 ();\par ?? stopwatch.Start();\par ?? \cf1 for\cf0 (\cf1 int\cf0 i = 0; i < Iterations; i++)\par ?? \{\par ?? action();\par ?? \}\par ?? stopwatch.Stop();\par ?? \cf4 Console\cf0 .WriteLine(name + \cf5 " took "\cf0 + (stopwatch.ElapsedMilliseconds / (\cf1 double\cf0 )Iterations) + \cf5 " ms"\cf0 );\par ?? \}\par ??\par ??\par ?? \cf1 private\cf0 \cf1 static\cf0 \cf1 void\cf0 GetCountryInfo(\cf1 string\cf0 ip)\par ?? \{\par ?? \cf4 IPAddress\cf0 ipAddress;\par ?? \cf1 if\cf0 (!\cf4 IPAddress\cf0 .TryParse(ip, \cf1 out\cf0 ipAddress)) \cf1 return\cf0 ;\par ?? ipAddress.Iso3166TwoLetterCode();\par ?? ipAddress.Iso3166ThreeLetterCode();\par ?? ipAddress.Country();\par ??\par ?? \}\par ??\par ??\par ??\par ?? \}\par ??\}\par ??} -->
 
 
namespace Client
{
 
 
    using System;
    using System.Diagnostics;
    using System.Net;
    using WorldDomination.Net;
 
    class Program
    {
 
 
        const int Iterations = 1000;
        static void Main(string[] args)
        {
 
             string ip = "65.55.11.218"; //US IP Address
 
            MeasureFormatTime("GetCountryInfo", () => GetCountryInfo(ip));
            Console.ReadLine();
        }
 
        static void MeasureFormatTime(string name, Action action)
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            for (int i = 0; i < Iterations; i++)
            {
                action();
            }
            stopwatch.Stop();
            Console.WriteLine(name + " took " + (stopwatch.ElapsedMilliseconds / (double)Iterations) + " ms");
        }
 
 
        private static void GetCountryInfo(string ip)
        {
            IPAddress ipAddress;
            if (!IPAddress.TryParse(ip, out ipAddress)) return;
            ipAddress.Iso3166TwoLetterCode();
            ipAddress.Iso3166ThreeLetterCode();
            ipAddress.Country();
 
        }
 
 
 
    }
}
The results of executing this code 1000 times:
current (lookup using list.FindBy) - GetCountryInfo took 40.632 ms

original (lookup using linq) - GetCountryInfo took 54.507 ms

lookup using IEnumerable.Where - GetCountryInfo took 47.154 ms - I tried to use the object IEnumerable<IPv4Data> and look up using Where.




Shay.