Class1 contains the RetrieveAll method that I'm trying to call from Class2. I just can't get this thing happy as it's not like the types I put in for my Generic list I guess. I've glossed over
the implementation of Class1 and it's returning an IEnumerable I guess:
Class1(hhDbRoleProvider):
namespace xxx.hh.Business.Entities
{
public class hhDbRoleProvider : IRoleProvider
{
public IRole New(string roleName)
{
return new Role(this)
{
RoleName = roleName,
Description = string.Empty
};
}
public IEnumerable RetrieveAllRoles()
{
List<IRole> roles = new List<IRole>();
using (IDataReaderEnumerable dalRoles = Role.RetrieveAll())
foreach (Role dalRole in dalRoles)
roles.Add(new Role(dalRole));
return roles;
}
}
}
Class2 (HHRoleProvider)
namespace xxx.hh.Common.Roles
{
classHHRoleProvider : RoleProviderBase
{
public override Configuration.Roles.Role[] GetRoles()
{
// Grab all the roles from the DB
hhDbRoleProvider roleProvider;
The error is on the last line and I cannot figure out how the hell to get it to be "happy":
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<xxx.BusinessInterfaces.Security.IRole>' to 'System.Collections.Generic.List<xxx.BusinessInterfaces.Security.IRole>'. An explicit conversion exists (are you missing a cast?)
I'm confused (understand that I get Generic lists but new to IEnumerable stuff and complex casting in situations like this)...and I also updated the RetrieveAllRoles() implementation in class 1 becasue the stupid editor in here took out half of what was there
which was this:
List
<IRole> roles =
new
List<IRole>();
So since RetrieveAllRoles is returning a Generic List of IRole, I still do not get why I can't set it to another Generic list of IRole in my Class 2. However the method
signature on that method in class 1 says IEnumerable so what the hell is it returning? Is it returning a generic list of IRole or simply an IEnumerable? I don't see how this works. I know that IEnumerable lets you iterate over a list. But I guess I don't
get this casting scenario.
If the method signature says IEnumerable, then that's what it is returning. List<T> can be implicitly cast to IEnumerable<T>, but you'll have to explicitly cast to go from IEnumerable<T> to List<T>:
IEnumerable<String> ienum = new List<String>();
List<String> list = (List<String>)ienum;
Marked as answer by dba123 on May 23, 2008 11:31 PM
Thanks, I'll have to research IEnumerable a bit more to really get this. I guess I also don't understand how it's returning an IEnumerable<> besides the method signature saying it's returning an IEnumerable when it's showing me that it's returning a generic
list of IRole. So somehow the compiler pushes in An IEnumerable<IRole>...I just don't get that. The return statement in that method is saying it's returning List<IRole> but method signature doesn't say List<IRole> it says IEnumerable. What are the symantics
of that?
But moving on, I now get this:
hhDbRoleProvider roleProvider;
List<xxx.BusinessInterfaces.Security.IRole> hhRoles =
new
List<xxx.BusinessInterfaces.Security.IRole>(roleProvider.RetrieveAllRoles());
I also tried:
hhDbRoleProvider roleProvider;
List<xxx.BusinessInterfaces.Security.IRole> hhRoles =
new
List<xxx.BusinessInterfaces.Security.IRole>();
because the one that comes with .NET doesn't support what we're doing. Our portal is very advanced and we're not going to extend the asp.net membership for this. We're using ASP.NET MVC and this provider will hook into our CMS system. I can't really explain,
it's that complicated of a system that we can't use the membership provider for our needs.
It is a little tricky - I've been doing C# for a couple of years and I'm still not completely clear on exactly what IEnumerable does.
As far as I can tell, List<T> is pretty much a strongly typed array with a bunch of really handy extra functionality. IEnumerable<T> isn't an array, but rather a non-indexed collection of objects that can be enumerated (meaning looped through). IEnumerable<T>
is the most basic interface that must be implemented by an object for it to support foreach.
If you use LINQ, or are at least familiar with it, it makes it a little easier to understand.
When you create a LINQ query or use a lambda expression, the result is returned as an IEnumerable<T> (or IQueryable<T>, which is nearly the same thing I believe). However, you can think of that as just a query. It doesn't actually contain any data itself,
it's just sort of a pointer to it.
The expression or query isn't actually executed until you iterate through it, or call a method like ToList(), ToArray() or ToDictionary(), which causes it to be enumerated.
dba123
Contributor
2726 Points
1364 Posts
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<xxx>' to 'System.Collectio...
May 23, 2008 07:53 PM|LINK
Class1 (hhDbRoleProvider):
namespace xxx.hh.Business.Entities { public class hhDbRoleProvider : IRoleProvider { public IRole New(string roleName) { return new Role(this) { RoleName = roleName, Description = string.Empty }; } public IEnumerable RetrieveAllRoles() {List<IRole> roles = new List<IRole>();
using (IDataReaderEnumerable dalRoles = Role.RetrieveAll()) foreach (Role dalRole in dalRoles) roles.Add(new Role(dalRole)); return roles; } } }Class2 (HHRoleProvider)
The error is on the last line and I cannot figure out how the hell to get it to be "happy":
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<xxx.BusinessInterfaces.Security.IRole>' to 'System.Collections.Generic.List<xxx.BusinessInterfaces.Security.IRole>'. An explicit conversion exists (are you missing a cast?)
Daniel Schaf...
Member
101 Points
29 Posts
Re: Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<xxx>' to 'System.Colle...
May 23, 2008 08:04 PM|LINK
You can't cast directly from IEnumerable<> to List<> because they aren't the same thing.
You can either use LINQ's ToList() method, or instantiate a new List<>:
dba123
Contributor
2726 Points
1364 Posts
Re: Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<xxx>' to 'System.Colle...
May 23, 2008 09:04 PM|LINK
List
<IRole> roles = new List<IRole>();So since RetrieveAllRoles is returning a Generic List of IRole, I still do not get why I can't set it to another Generic list of IRole in my Class 2. However the method signature on that method in class 1 says IEnumerable so what the hell is it returning? Is it returning a generic list of IRole or simply an IEnumerable? I don't see how this works. I know that IEnumerable lets you iterate over a list. But I guess I don't get this casting scenario.
Daniel Schaf...
Member
101 Points
29 Posts
Re: Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<xxx>' to 'System.Colle...
May 23, 2008 09:12 PM|LINK
If the method signature says IEnumerable, then that's what it is returning. List<T> can be implicitly cast to IEnumerable<T>, but you'll have to explicitly cast to go from IEnumerable<T> to List<T>:
IEnumerable<String> ienum = new List<String>();
List<String> list = (List<String>)ienum;
dba123
Contributor
2726 Points
1364 Posts
Re: Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<xxx>' to 'System.Colle...
May 23, 2008 09:22 PM|LINK
Thanks, I'll have to research IEnumerable a bit more to really get this. I guess I also don't understand how it's returning an IEnumerable<> besides the method signature saying it's returning an IEnumerable when it's showing me that it's returning a generic list of IRole. So somehow the compiler pushes in An IEnumerable<IRole>...I just don't get that. The return statement in that method is saying it's returning List<IRole> but method signature doesn't say List<IRole> it says IEnumerable. What are the symantics of that?
But moving on, I now get this:
hhDbRoleProvider roleProvider; List<xxx.BusinessInterfaces.Security.IRole> hhRoles = new List<xxx.BusinessInterfaces.Security.IRole>(roleProvider.RetrieveAllRoles());I also tried:
hhDbRoleProvider roleProvider; List<xxx.BusinessInterfaces.Security.IRole> hhRoles = new List<xxx.BusinessInterfaces.Security.IRole>();hhRoles = (
List<xxx.BusinessInterfaces.Security.IRole>)roleProvider.RetrieveAllRoles();Either way I still get this error: Use of unassigned local variable 'roleProvider'
What is it talking about, I DID use it.
Daniel Schaf...
Member
101 Points
29 Posts
Re: Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<xxx>' to 'System.Colle...
May 23, 2008 09:45 PM|LINK
You've declared it, but you haven't assigned a value to it or instantiated it.
hhDbRoleProvider roleProvider = new hhDbRoleProvider();
Or whatever constructor or method you have of instantiating hhDbRoleProvider.
Also, just out of curiosity, why are you creating your own role provider instead of just using the one that comes with ASP.NET?
dba123
Contributor
2726 Points
1364 Posts
Re: Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<xxx>' to 'System.Colle...
May 23, 2008 10:14 PM|LINK
because the one that comes with .NET doesn't support what we're doing. Our portal is very advanced and we're not going to extend the asp.net membership for this. We're using ASP.NET MVC and this provider will hook into our CMS system. I can't really explain, it's that complicated of a system that we can't use the membership provider for our needs.
dba123
Contributor
2726 Points
1364 Posts
Re: Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<xxx>' to 'System.Colle...
May 23, 2008 10:15 PM|LINK
There is an implicit constructor I guess since the dude did not define one in class1
dba123
Contributor
2726 Points
1364 Posts
Re: Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<xxx>' to 'System.Colle...
May 23, 2008 10:19 PM|LINK
In the end this seems to work:
hhDbRoleProvider roleProvider = new hhDbRoleProvider(); List<xxx.BusinessInterfaces.Security.IRole> hhRoles = (List<xxx.BusinessInterfaces.Security.IRole>)roleProvider.RetrieveAllRoles();Thanks for your help. I have a long way to go to understanding casting for this and IEnumerable stuff.
Daniel Schaf...
Member
101 Points
29 Posts
Re: Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<xxx>' to 'System.Colle...
May 24, 2008 01:24 AM|LINK
It is a little tricky - I've been doing C# for a couple of years and I'm still not completely clear on exactly what IEnumerable does.
As far as I can tell, List<T> is pretty much a strongly typed array with a bunch of really handy extra functionality. IEnumerable<T> isn't an array, but rather a non-indexed collection of objects that can be enumerated (meaning looped through). IEnumerable<T> is the most basic interface that must be implemented by an object for it to support foreach.
If you use LINQ, or are at least familiar with it, it makes it a little easier to understand.
When you create a LINQ query or use a lambda expression, the result is returned as an IEnumerable<T> (or IQueryable<T>, which is nearly the same thing I believe). However, you can think of that as just a query. It doesn't actually contain any data itself, it's just sort of a pointer to it.
The expression or query isn't actually executed until you iterate through it, or call a method like ToList(), ToArray() or ToDictionary(), which causes it to be enumerated.
I hope that helps... good luck! :)