How to cast list to enumerable - c#

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>.

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();

GetEnumerator returns null

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();

Anonymous type scoping issue

What is the proper way to create a variable that will house a list of anonymous objects that are generated through a LINQ query while keeping the variable declaration outside of a try/catch and the assignment being handled inside of a try/catch?
At the moment I'm declaring the variable as IEnumberable<object>, but this causes some issues down the road when I'm trying to use it later...
i.e.
var variableDeclaration;
try{
...
assignment
...
}catch...
EDIT:
If it's relevant (don't think it is) the list of objects is being returned as a Json result from an MVC3 action. I'm trying to reduce the time that some using statements are open with the DB as I'm having some performance issues that I'm trying to clear up a bit. In doing some of my testing I came across this issue and can't seem to find info on it.
EDIT 2:
If I could request the avoidance of focusing on LINQ. While LINQ is used the question is more specific to the scoping issues associated with Anonymous objects. Not the fact that LINQ is used (in this case) to generate them.
Also, a couple of answers have mentioned the use of dynamic while this will compile it doesn't allow for the usages that I'm needing later on the method. If what I'm wanting to do isn't possible then at the moment the answer appears to be to create a new class with the definition that I'm needing and to use that.
It's possible to get around this by creating a generic Cast method as outlined by Jon Skeet here. It will work and give you the intellisense you want. But, at this point, what's wrong with creating a custom type for your linq method?
public class MyClass
{
public int MyInt { get; set; }
}
IEnumerable<MyClass> myClass =
//Some Linq query that returns a collection of MyClass
Well, if you're using LINQ, the query is not evaluated unless materialized...
So, you might be able to:
var myQuery = //blah
try
{
myQuery = myQuery.ToList(); //or other materializing call
}
catch
{
}
Could you perhaps get away with using dynamic ??
dynamic variableDeclaration;
try
{
variableDeclaration = SomeList.Where(This => This == That);
}
catch { }
Not sure what this will affect further in your code block, but just a thought :)
If you are declaring the variable ahead of using it like a try/catch you can't use [var] as it is intendend. Instead you have to type the the variable.
var x = 0;
try{
x = SomethingReturningAnInt();
}
or
int x;
try{
x = SomethingReturningAnInt();
}
However in your case you don't really "know" what the method returns
var x = ...;
try{
x = Something();
}
catch{}
won't work
Option you have when you don't know the type in advance is use of dynamic:
dynamic x;
try{
x = Something();
}
catch{}
(But that feels like going back to VB4)
Another cheat: you can define variable locally (similarly to Jon's hack in Dave Zych answer) and than use it inside try/catch. As long as you can create the same anonymous item type before try-catch you are OK (as anonymous types wit the same field names and types are considered the same):
var myAnonymouslyType = Enumerable.Repeat(
new {Field1 = (int)1, Field2 = (string)"fake"}, 0);
try
{
myAnonymouslyType = ...(item =>
new {Field1 = item.Id, Field2=item.Text})...
}
...
This is safer option than covered in Jon's casting of anonymous types between functions because compiler will immediately find errors if types don't match.
Note: I'd vote for non-anonymous type if you have to go this way...
Note 2: depending on your actual need consider simply returning data from inside try/catch and having second return of default information outside.
This has vexed me for a while. In the end I've build some Generic helper methods where I can pass in the code that generates the anonymous objects, and the catch code as lamdas as follows
public static class TryCatch
{
public static T Expression<T>(Func<T> lamda, Action<Exception> onException)
{
try
{
return lamda();
}
catch(Exception e)
{
onException(e);
return default(T);
}
}
}
//and example
Exception throwexception = null;
var results = TryCatch.Expression(
//TRY
() =>
{
//simulate exception happening sometimes.
if (new Random().Next(3) == 2)
{
throw new Exception("test this");
}
//return an anonymous object
return new { a = 1, b = 2 };
} ,
//CATCH
(e) => { throwexception = e;
//retrow if you wish
//throw e;
}
);
https://gist.github.com/klumsy/6287279

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.

Can this Linq query be typed as anything other than "var"?

When I do a query that returns an anonymous type
var assets =
from Product p in Session.CreateLinq<Product>()
where bundles.Contains(p.ProductBundle)
select new {p.Asset, p.Asset.PropertyTbl};
Can I type the return to anything other than var?
You cannot* return an anonymous type because the caller would not know what type it is and wouldn't be able to use it.
If you want to return the results, you can create objects of a non-anonymous type:
IEnumerable<Foo> assets =
from Product p in Session.CreateLinq<Product>()
where bundles.Contains(p.ProductBundle)
select new Foo { Bar = p.Asset, Baz = p.Asset.PropertyTbl};
You can also use the Tuple type in .NET 4 if you don't want to create a custom class for your values.
* This is not strictly true - it is possible but you should avoid doing it. Here is a link anyway if you really want to.
You can use object or dynamic (in .NET 4.0) instead of var but don't expect to find a name to an anonymous type. In your case using var is better as it will preserve the strong typing at least until you leave the scope of the current method.
You could define a new class:
public class AssetProp
{
public virtual string Asset {get;set;}
public virtual string PropertyTbl {get;set;}
}
And then you can return it as that class:
IEnumerable<AssetProp> assets =
from Product p in Session.CreateLinq<Product>()
where bundles.Contains(p.ProductBundle)
select new AssetProp {p.Asset, p.Asset.PropertyTbl};
Not really, since the new {p.Asset, p.Asset.PropertyTbl} code creates an anonymous type. Even using object doesn't really gain you much since you can't cast it to anything useful later on, so you would have to use reflection to access the properties.
Not really. If you cast to object you wont be able to access the properties of your anonymous class.
The var keyword was specifically introduced for dealing with anonymous classes - why would you want to avoid it? If you need to return the data you should name the class.
You can if you use lambda expressions, otherwise you can do a cast but do some good exception handling.
you can also do this (it does relate much to your problem though, because you just move "var" somewhere else, but it's interesting that it recognize those types as same)
var element = new { id = 7 };
List<object> collection = new List<object>();
element = collection.Select(item => new { id = 0 }).First();

Categories

Resources