locked
Unable to Cast a Linq Where Query Using Blazor Singleton Services Classes RRS feed

  • Question

  • User-343630552 posted

    I am trying to learn Blazor Wasm using a small demo app.  I have created two Blazor Services Classes as shown below.  I am able to use the 1st one to instantiate 10 BBDetail objects and to then populate the List<BBDetail> in the 2nd one with those objects.  After that, using the "Works Correctly" statements, I am able to assign the list in the Services class to a local list (without casting) and to pull out the first object with a Year of 2018.  So far so good.  But the "Doesn't Work" statements don't work.  The Where assignment in the 1st statement doesn't blow up and the var whereBBD ends up  a List<BBDetail>, but it is empty.  Then, the 2nd Where assignment blows up with a "Specified cast is not valid" exception.  Obviously there is at least one object with Year == 2018 in the list since the First assignment returns an object.

    Any idea what's going on?  Thanks.  Steve

    // Works Correctly
    List<BBDetail> lclBBDetailList = D_.BBDetailList;
    BBDetail oneBBD = lclBBDetailList.First(x => x.Year == 2018);
    
      
    // Doesn't Work - Cast Not Valid Error 
    var whereBBD = lclBBDetailList.Where(x => x.Year == 2018);   
    List<BBDetail> listBBD = (List<BBDetail>)lclBBDetailList.Where(x => x.Year == 2018);
    
    // Blazor Services Class #1
    namespace ME_Web.Services
    {
        public class BBDetail
    	{
    	// Note that if this doesn't match the json object, no error is thrown
    	public string BBName { get; set; }
    	public string BBTName { get; set; }
    	public int Year { get; set; }
    	public string VblName { get; set; }
    	public int Nature { get; set; }
    	public int Format { get; set; }
    	public int Flags { get; set; }
    	public decimal DecValue { get; set; }
    	public string StringValue { get; set; }
    
    	public BBDetail() { }
    
    	public BBDetail(string bbName, string bbtName, int year, string vblName, int nature, int format, int flags, decimal decValue, string stringValue)
    		{
    		BBName = bbName;
    		BBTName = bbtName;
    		Year = year;
    		VblName = vblName;
    		Nature = nature;
    		Format = format;
    		Flags = flags;
    		DecValue = decValue;
    		StringValue = stringValue;
    		}
    	}
    }

    // Blazor Services Class #2
    namespace ME_Web.Services
    {
    public class D_
    {
    public List<BBDetail> BBDetailList { get; set; }
    }
    }

    Friday, June 26, 2020 6:14 PM

Answers

  • User303363814 posted

    The object returned by .Where is not something which can be cast to a List.  If you want a List then use the .ToList() method.  

    var listBBO = lclBBDetailList.Where(x => x.Year == 2018).ToList();

    What method do you use to decide that whereBBD has no elements?  In can sometimes be confusing to examine the results of linq queries in the debugger.  Execution is generally delayed as long as possible so that it can be as efficient as possible.  The result of a .Where method is not determined until the result is needed and appears to be empty in the debugger until that time.  ToList() is one way to force an evaluation.

    But ... if your code doesn't need a List then don't force one to be created.  The runtime works much more efficiently if you let it do its job.

    (BTW - expressions like 'blow up' are colorful but not useful.  Programming is all about detail.  What precisely happens? Or what precise result is returned if it "doesn't blow up".)

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, June 26, 2020 10:50 PM

All replies

  • User303363814 posted

    The object returned by .Where is not something which can be cast to a List.  If you want a List then use the .ToList() method.  

    var listBBO = lclBBDetailList.Where(x => x.Year == 2018).ToList();

    What method do you use to decide that whereBBD has no elements?  In can sometimes be confusing to examine the results of linq queries in the debugger.  Execution is generally delayed as long as possible so that it can be as efficient as possible.  The result of a .Where method is not determined until the result is needed and appears to be empty in the debugger until that time.  ToList() is one way to force an evaluation.

    But ... if your code doesn't need a List then don't force one to be created.  The runtime works much more efficiently if you let it do its job.

    (BTW - expressions like 'blow up' are colorful but not useful.  Programming is all about detail.  What precisely happens? Or what precise result is returned if it "doesn't blow up".)

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, June 26, 2020 10:50 PM
  • User-343630552 posted

    Thanks, Paul.  This is one of those questions where I'm glad I don't have my full name exposed...embarrassing.  As someone who is brand new to web programming, I think I have been overwhelmed at times trying to learn by reading and trial-and-error alone such a daunting set of technologies all at once .  I know about the ToList() need from my WinForms work.  

    I appreciate the reminder/heads-up  on the linq deferred execution.   It never registered that a debugger examination might be misleading for that reason (even in the Immediate Window?).

    Last, I understand not being a fan of colorful language such as "blow up" in the absence of the detail, but I did mention the all-important invalid cast exception.  I guess I picked up this colorful language as a mainframe systems programmer in the 60s, and hey, the lengthy bright red exception message in the console log does kind of look like an explosion.  :-) 

    Anyway, thanks again for the help.  Now on to the next faux pas.  Steve

    Saturday, June 27, 2020 11:20 AM