1

I get the following exception:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object. at GoogleProducts.Program.<Main>d__0.MoveNext() in C:\Code\test\GoogleProducts\Program.cs:line 60 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at GoogleProducts.Program.<Main>(String[] args)

the source is:

private static async Task Main(string[] args)
        {
            var queries = new[]
            {
                "seico watch",
                "citizen watch",
                "orient watch",
                "bulova watch",
                "seagull watch",
                "glashuette watch"
            };

            var client = new WebClient();

            foreach (var query in queries)
            {
                var url = @"https://www.google.co.uk/search?tbm=shop&q=" + query;
                var content = await client.DownloadStringTaskAsync(url);

                var doc = new HtmlDocument();
                doc.LoadHtml(content);

                var linkedProducts = doc.DocumentNode.Descendants("a")
                    .Select(a => a.GetAttributeValue("href", null))
                    .Where(href => href.StartsWith(@"/shopping/product/"));

                var productTasks = linkedProducts.Select(async linkedProduct =>
                {
                    var productUrl = @"https://www.google.co.uk" + linkedProduct;

                    var productPage = await client.DownloadStringTaskAsync(productUrl);
                    var productDoc = new HtmlDocument();
                    productDoc.LoadHtml(productPage);

                    var productName = productDoc.DocumentNode.Descendants("title").FirstOrDefault()?.InnerText;

                    var sellersNodes = productDoc.DocumentNode.Descendants("tr")
                        .Where(tr => tr.GetAttributeValue("class", null) == "os-row");

                    var sellers = sellersNodes.Select(seller => new Seller
                    {
                        Name = seller.Descendants("a").First().InnerText,
                        Price = decimal.Parse(seller.Descendants("td").Last().InnerText.Substring(2))
                    }).ToArray();

                    return sellers.Any() ? new Product(sellers, productName) : null;
                }).Where(product => product != null);

                foreach (var productTask in productTasks)
                {
                    var product = await productTask;
                    var result =
                        $"{product.Name}{Environment.NewLine}Best price: {product.BestPrice()}, from {product.BestPriceSellers()}"
                        + $", Average price: {product.AveragePrice()}";

                    Console.WriteLine(result + Environment.NewLine);
                }
            }
        }

Can't post without more details.

Henk Holterman
  • 236,989
  • 28
  • 287
  • 464
Test45
  • 433
  • 1
  • 4
  • 12

1 Answers1

4

You are executing ).Where(product => product != null); on a a list of Task<Product>, not of Product.

So even when the Product is null, the Task<Product> is not.

To see it better, specify the type:

 .Where((Task<Product> product) => product != null);

this should compile and show you how wrong naming can trick you.

Eric Lippert
  • 612,321
  • 166
  • 1,175
  • 2,033
Henk Holterman
  • 236,989
  • 28
  • 287
  • 464