none
Cast IList as ArrayList. RRS feed

  • General discussion

  • Hi,

    I'm recoding a application written in C # .NET3.5 for the .NET4.7.1.
    There is a block of code, which although not elegant but works in .NET3.5:

    private static Hashtable buildServiceLists(IList accountServices, IList aliasServicesView)
    {
    	Hashtable lists = new Hashtable();
    
    	((ArrayList)accountServices).AddRange(aliasServicesView); // this not work in .NET 4.7.1
    
    	// Generating hashTable of services
    	foreach (AccountServiceView acs in accountServices)
    	{
    		//treatmet process
    	}
    	return lists;
    }


    If I do the same thing in .NET 4.7.1 I get an error:
     System.InvalidCastException: Unable to cast object of type 'System.Collections.ArrayList' to type 'System.Collections.Generic.List' 1[com.abc.objects.orm.AccountServiceView]

    Could someone explain to me why this works in .NET 3.5?


    William John Adam Trindade
    Analyste-programmeur


    Sogi Informatique ltée
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, remember to "Mark as Answer". Se achou este post útil, por favor clique em "Votar como útil". Se por acaso respondeu sua dúvida, lembre de "Marcar como Resposta".


    Friday, June 22, 2018 3:51 PM

All replies

  • This is an issue with your argument to the method, not the code itself.

    In your method you are doing a runtime case of an IList to ArrayList. If the argument that is being passed in is truly an ArrayList then this cast will work. If it isn't then you get an exception. 

    //Will work
    buildServiceLists(new ArrayList(), new ArrayList());
    
    //Will not work
    buildServiceLists(new List<string>(), new ArrayList());

    The language has always worked this way so changing back to 3.5 wouldn't have any impact whatsoever unless the argument had a different base type in 3.5. Since you didn't post that we cannot tell but I'd recommend you look at the argument you're passing to the method. 


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, June 22, 2018 5:23 PM
    Moderator
  • I not changing the call.

    If inspect the paramater accountServices in VS2010 I get this:

    - accountServices Count = 2 System.Collections.IList {System.Collections.ArrayList}

    and in VS2017 I get this:

    Name Value Type
    accountServices Count = 2 System.Collections.IList {System.Collections.ArrayList}

    Same type, same content, but I get an exception if I try cast as ArrayList in VS2017.



    William John Adam Trindade
    Analyste-programmeur


    Sogi Informatique ltée
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, remember to "Mark as Answer". Se achou este post útil, por favor clique em "Votar como útil". Se por acaso respondeu sua dúvida, lembre de "Marcar como Resposta".

    Friday, June 22, 2018 5:46 PM
  • Can you not go to the actual place in your code where you're calling this method and look at the type of the argument being passed in?

    You aren't trying to mix framework versions across assemblies are you? For example you're not trying to get a .NET 4.7.1 assembly to run against a .NET 3.5 assembly or vice versa.


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, June 22, 2018 6:05 PM
    Moderator
  • >Can you not go to the actual place in your code where you're calling this method and look at the type of the argument being passed in?

    Yes. I not changed the call:

     public static AccountServicesData loadServiceLists(Account account)
    {            IList accountServices = AccountServiceCtl.loadStandAloneServicesView(account);
                IList aliasServicesView=getAliasesServices(account);
                if (accountServices != null)
                    return new AccountServicesData(AccountServicesData.buildServiceLists(accountServices, aliasServicesView));
                else
                    return null;
    }
    
     public static IList loadStandAloneServicesView(Account account)
            {
                ISession session = AccountServiceViewDAO.getInstance().getCurrentSession();
                ICriteria criteria = session.CreateCriteria(typeof(AccountServiceView));
                criteria.Add(Restrictions.Eq("account_id", account.getId()));
                criteria.Add(Restrictions.IsNull("account_package_id"));
                criteria.AddOrder(Order.Asc("description"));
                return criteria.List();
            }

    >You aren't trying to mix framework versions across assemblies are you? 

    No. All librarys are changed to .NET4.7.1.


    William John Adam Trindade
    Analyste-programmeur


    Sogi Informatique ltée
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, remember to "Mark as Answer". Se achou este post útil, por favor clique em "Votar como útil". Se por acaso respondeu sua dúvida, lembre de "Marcar como Resposta".

    Friday, June 22, 2018 6:24 PM
  • Is that really what the error said, and you're sure that's the line with the error?  Because the error message is backwards from what you're trying to do.  The error message complains about casting an ArrayList to a Generic.List, but you're trying to cast an IList to an ArrayList.  Further, I don't see where Generic.List is involved at all.

    You're assuming the error is in the cast, but I'm wondering if it's complaining about the aliasServicesView, when it tries to automatically cast it to an ICollection to pass it to AddRange.  The error message does reference AccountServiceView.

    Of course, even if that's true, I still can't explain why it's a problem.  If aliasServicesView is an ArrayList coming in as an IList, it should become an ICollection without any fuss.


    Tim Roberts, Driver MVP Providenza & Boekelheide, Inc.

    Friday, June 22, 2018 6:27 PM
  • Please post the code for your List method on your ICriteria object which looks to be of type AccountServiceView.

    If you're just interested in getting your code working then change the AddRange call. It isn't actually correct (in my opinion) anyway. You are using interfaces all over your code which means you don't care about the underlying implementation. But this particular method is assuming an ArrayList which would only be valid if the interface object was in fact an ArrayList. To make your code less brittle, break it into a simple foreach loop or you could cheat and force a conversion to IEnumerable<object> (or whatever you expect to store in the list) and then use its AddRange method.


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, June 22, 2018 6:30 PM
    Moderator
  • List is a native method for NHibernate.

    >If you're just interested in getting your code working then change the AddRange call. It isn't actually correct (in my opinion) anyway.

    Is my opinion too. I've changed this method. Now the "query" returns all collection and we don't need do an addrange. 

    Sorry, this post should be a discussion and not a question. 


    The problem has already been fixed, but I found it curious that this method works (and in my opnion should not work) in .NET 3.5 and stopped working when I switched to .NET 4.7.1

    William John Adam Trindade
    Analyste-programmeur


    Sogi Informatique ltée
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, remember to "Mark as Answer". Se achou este post útil, por favor clique em "Votar como útil". Se por acaso respondeu sua dúvida, lembre de "Marcar como Resposta".

    Tuesday, June 26, 2018 3:18 PM