GetEnumerator returns null - c#

Object htmlDocument.Body.All is not null. Why does GetEnumerator() return null?
IEnumerator<HtmlElement> hm = htmlDocument.Body.All.GetEnumerator() as
IEnumerator<HtmlElement>;

I think you want this. Although why you want an Enumerator<HtmlElement> I have no clue.
IEnumerator<HtmlElement> hm = htmlDocument.Body.All
.OfType<HtmlElement>()
.GetEnumerator();
In most cases you will find that you can do things much more easily with
foreach(var element in htmlDocument.Body.All.OfType<HtmlElement>())
{
//Stuff
}

You are casting it using as and if as fails, it returns null. Try it like this, to see what the exact return type is without assuming anything or casting:
var hm = htmlDocument.Body.All.GetEnumerator();

Related

Convert System.Linq.IOrderedEnumerable<T> to List<T>

.NET compiler will not implicitly convert System.Linq.IOrderedEnumerable<T> to System.Collections.Generic.List<T>
An explicit cast:
using System.Collections.Generic;
var items = new List<MyType>;
var selectedItems =
from item in items
where item.Active
select item;
return (List<MyType>)selectedItems;
gives this warning:
Suspicious cast: there is no type in the solution which inherits from
both System.Linq.IOrderedEnumerable and
System.Collections.Generic.List
What is best practice here?
Simply use the ToList extension:
return selectedItems.ToList();
You should be aware though: best practice (since you asked) would actually want you to return an IEnumerable<MyType> in most cases. Therefore, you may want to change your signature in this way:
public IEnumerable<MyType> MyFunction()
{
// your code here
}
And THEN, if you need to, have the function's result in a list:
var myList = MyFunction().ToList();
Unless you have a very precise reason of returning a List<> type, I strongly suggest that you don't.
Hope that helps.
Use the System.Linq.Enumerable.ToList<T>() extension:
selectedItems.ToList();

return a List< Id:int, Name:string>

I am having a function which return a list of type: List< Id:Name, Name:string >
how do you do specify in C# to return this List Type ?
Here is the code:
public ?????? GetDepartements( int idRegion )
{
var a = (from o in _meilleurPrestaEntities.Departements
where o.de_id_region == idRegion
select new {Id = o.id_departement, Name = o.nom}).ToList();
return a;
}
the return is used as Json result.
thanks
I'd suggest using a key value pair
return List<KeyValuePair<int,string>>()
[Edit] You'll need to modify your code slightly - it should look something like this:
var a = (from o in _meilleurPrestaEntities.Departements
where o.de_id_region == idRegion
select new KeyValuePair<int,string>(o.id_departement,o.nom}).ToList();
You can't. You have a list of anonymous type and you can't specify anonymous type as part of a method return type (or pretty much anywhere else, unless you can use var).
To fix this, you have several options:
Create normal class to represent the return type and use that in your return type.
Use something like List<Tuple<int, string>>.
Return List<dynamic>. This way, you will be able to treat the returned value as usual, but you will get no compile-time checking or IntelliSense.
Return List<object>. This can be useful if you don't need to access the properties in the usual way, but you will only pass the result to something that uses reflection.
I think you have to specify a type and then use that type for your return value and in your select statement.
I don't have VisualStudio open to try it, but I think you can actually return dynamic in this case. Or you could use ExpandoObject.
However, as others have mentioned, the "better" way is to use something like Tuple or KeyValuePair, or don't be lazy and just make an actual model for what you will return to the view (in other words, a "View Model").

C# Generics: How can I use them generically?

[TestMethod]
public void TestMyGenericBaseClasses()
{
Type typeCrazy = ThisPartyIsTypeCrazyWOOT();
// How do I create a generic object?
MadnessOhYeah<typeCrazy> sanity = new MadnessOhYeah<typeCrazy>();
// How do I use a generic object after it has been created?
Assert.IsTrue(sanity.MyTrueFunction(), "this is sparta");
// How do I call a generic function generically?
bool result = MyFunction<typeCrazy>();
Assert.IsTrue(result, "I did not get my teeth whitened!");
}
Is there any way to make this compile? (ThisPartyIsTypeCrazyWOOT returns a Type) Because this is a test, we're not concerned about having to use reflection or anything, unless that's just absolutely crazy.
I'm getting the vibe that this isn't going to be possible though, and that our test functions will just have to be more specific.
You need Type.MakeGenericType Method. Then Activator.CreateInstance Method.
Update 2: The first example I posted still doesn't 100% answer the question, since it involves a cast to List<int>, which is a type that is known at compile time. Below is a reflection-only solution that illustrates how you can use a generic type knowing nothing about the type argument itself. But, as you can see, it's... well, disgusting ;)
Type userType = GetUserSuppliedType();
// Now let's say userType is T.
// Then here we are getting the type typeof(List<T>).
// But, of course, there's no way to have any such information in the code.
Type listOfUserType = typeof(List<>).MakeGenericType(new[] { userType });
// This is effectively calling new List<T>();
object listObject = Activator.CreateInstance(listOfUserType);
// Do you see how messy this is getting?
MethodInfo addMethod = listOfUserType.GetMethod("Add");
// We better hope this matches userType!
object input = GetUserSuppliedInput();
// I suppose we could check it, to be sure...
if (input == null || input.GetType() != userType)
{
throw new InvalidOperationException("That isn't going to work!");
}
// Here we are finally calling List<T>.Add(input) -- just in the most ass-
// backwards way imaginable.
addMethod.Invoke(listObject, new[] { input });
Update: OK, if you insist on doing this, here's an example of how it's possible—but very cumbersome!
Type genericListType = typeof(List<>);
Type listOfInt32Type = genericListType.MakeGenericType(new[] { typeof(int) });
object listObject = Activator.CreateInstance(listOfInt32Type);
List<int> list = (List<int>)listObject;
list.Add(1);
Generics can't quite work like this because a Type object could be anything. Consider this code:
var list = new List<int>();
list.Add(1);
The type of list in the above code is known to be List<int>, which defines what operations are legal on list such as Add(1).
Now consider this instead:
Type t = GetTypeFromIndeterminateSourceSuchAsUserInput();
var list = new List<t>();
list.Add(?);
When t is a Type object rather than the name of a type (like int) which the compiler can parse, it's not really possible to instantiate a generic type using that type—or rather, it's possible (see Andrey's answer), but you can't really use the resulting object in any sort of generic way.
Now, you might think that something like this ought to work:
Type t = typeof(int);
var list = new List<t>();
list.Add(1);
...but just because the value of t is known (by you) at compile time doesn't change the way things work in general.
Anyway, yes it's possible using reflection; but if you go down that path, you're committing to a pretty reflection-heavy solution. What I'm getting at is that in general it isn't a particularly realistic thing to do.

Get the Count of a List of unknown type

I am calling a function that returns an object and in certain circumstances this object will be a List.
A GetType on this object might gives me:
{System.Collections.Generic.List`1[Class1]}
or
{System.Collections.Generic.List`1[Class2]}
etc
I don't care what this type is, all I want is a Count.
I've tried:
Object[] methodArgs=null;
var method = typeof(Enumerable).GetMethod("Count");
int count = (int)method.Invoke(list, methodArgs);
but this gives me an AmbiguousMatchException which I can't seem to get around without knowing the type.
I've tried casting to IList but I get:
Unable to cast object of type 'System.Collections.Generic.List'1[ClassN]' to type 'System.Collections.Generic.IList'1[System.Object]'.
UPDATE
Marcs answer below is actually correct. The reason it wasn't working for me is that I have:
using System.Collections.Generic;
at the top of my file. This means I was always using the Generic versions of IList and ICollection. If I specify System.Collections.IList then this works ok.
Cast it to ICollection and use that .Count
using System.Collections;
List<int> list = new List<int>(Enumerable.Range(0, 100));
ICollection collection = list as ICollection;
if(collection != null)
{
Console.WriteLine(collection.Count);
}
You could do this
var property = typeof(ICollection).GetProperty("Count");
int count = (int)property.GetValue(list, null);
assuming you want to do this via reflection that is.
Use GetProperty instead of GetMethod
You can do this
var countMethod = typeof(Enumerable).GetMethods().Single(method => method.Name == "Count" && method.IsStatic && method.GetParameters().Length == 1);
This could help...
if (responseObject.GetType().IsGenericType)
{
Console.WriteLine(((dynamic) responseObject).Count);
}

How to cast list to enumerable

I've got a problem with the following code:
public IEnumerable<ISession> GetSessions()
{
// ...
using (ProvaDbEntities DBEntities = new ProvaDbEntities(Utilities.ToEntitiesConnectionString()))
{
ObjectQuery<session> sessions = DBEntities.session;
IEnumerable<session> q1 = from session in sessions
where session.site == this.Name
select session;
List<Session> sessionList = new List<Session>();
foreach (var s in q1)
{
sessionList.Add(new Session(s.id.ToString(),s.username, s.site, new DateTime()));
}
IEnumerable<Session> res = sessionList;
return sessionList;
}
}
The exception is:
Is not possible to cast object type 'System.Collections.Generic.List`1[prova3.Session]' to type 'System.Collections.Generic.IEnumerable`1[TAP2009.AuctionSite.Interfaces.ISession]'.
Looking at this SO question it seems to be correct. Am I wrong?
It should be fine, so long as Session implements ISession - if you're using C# 4 and .NET 4. If you're not, it won't be.
Note that the question you referred to use the same "T" in both cases - whereas the exception you've got is about converting a List<Session> to an IEnumerable<ISession>. You haven't stated where you're getting the exception, which makes it a bit harder to see exactly what's going on... Are you sure this is actually the code which is failing? Are you sure you're getting an exception rather than a compile-time failure?
EDIT: If you're not using .NET 4 and C# 4, the workaround for covariance is reasonably simple here - use the Cast<T>() LINQ operator:
return sessionList.Cast<ISession>();
Have you tried using the extension method AsEnumerable()?
So this line
IEnumerable<Session> res = sessionList;
Would change to
IEnumerable<Session> res = sessionList.AsEnumerable();
The return type is public IEnumerable<ISession>, i forgot to specify the type of the Ienumerable..
You can add using System.Linq and use the extension method Cast<T> that returns a IEnumerable<T>.

Categories

Resources