I have the following code:
public IList<MyObject> GetSomeData(string inputParam)
{
var temp = repository.GetData(inputParam);
var list = temp as List<MyObject>;
return list;
}
The return value of repository.GetData is IEnumerable<IMyObject>
When I look at the value of temp, it has 400+ records. The moment I cast it to list, it becomes null. Why is this cast not possible?
It returns null because that IEnumerable isn't actually a list. The cast will only succeed if that particularly IEnumerable happens to be a List, instead of some other type of sequence. If you want to have a list, you will need to create a new list and add the items from the sequence into that list.
Unless the underlying object of the value returned from repository.GetData matches what you are trying to cast it to then the result will always be null. Because the generic element types of the method and what is actually return from repository.GetData are different you will need to do some conversions to get the desired result
Assuming that MyObject implements IMyObject I can think of at least to ways using System.Linq to get the result you seek.
Option 1: Cast<T>()
Casts the elements of an System.Collections.IEnumerable to the specified type.
First convert the content of temp using the Cast<MyObject>() linq extension and then use the ToList<T>() extension method to get you resulting IList<MyObject>
public IList<MyObject> GetSomeData(string inputParam)
{
//repository.GetData returns IEnumerable<IMyObject>
var temp = repository.GetData(inputParam);
var list = temp.Cast<MyObject>().ToList();
return list;
}
Option 2: OfType<T>()
Filters the elements of an System.Collections.IEnumerable based on a specified type.
Filter the content of temp using the OfType<MyObject>() linq extension and then use the ToList<MyObject>() extension method to get you resulting IList<MyObject>
public IList<MyObject> GetSomeData(string inputParam)
{
//repository.GetData returns IEnumerable<IMyObject>
var temp = repository.GetData(inputParam);
var list = temp.OfType<MyObject>().ToList();
return list;
}
Related
When using IEnumerable I'm trying to avoid multiple enumerations. I know I can just use LINQ's .ToList() and be done with it, but that can be a lot of unnecessary list creation. I'd like to:
check and see if the underlying type is a List, and if so return that instance, otherwise
.ToList() it and return the new List
My thought was to use something akin to:
public void Fee()
{
var list = new List<string>(); // I want to retrieve this instance in Foo
Foo(list);
}
public void Foo(IEnumerable<T> enumerable)
{
var list = enumerable as List<T> ?? enumerable.ToList();
// do stuff with original list
}
... but it appears from the documentation that the as operator just performs a cast, which would create a new List rather than returning the underlying one, would it not?
If so, how can I retrieve the underlying list instead of creating a new one?
The as operator does not create a new list. It only checks type and perform cast if type is compatible.
The code in the post is logically correct and matches how many LINQ methods are implemented (for example see source of Enumerable.Count which casts to ICollection to see if it can skip enumeration of items).
Note that it is important to cast to correct generic version of list or maybe one of its interfaces - IList would work if you must use non-generic version. Beware of the fact that List<T> is not co/contra-variant and type must match exactly unlike in case of covariant IEnumerable<out T> where you can cast parameter to IEnumerable<TBase> if IEnumerable<TDerived> passed.
Maybe you wanted to do this:
public void Fee()
{
var list = new List<string>(); // I want to retrieve this instance in Foo
Foo(list);
}
public void Foo<T>(IEnumerable<T> enumerable)
{
List<T> list = enumerable as List<T> ?? enumerable.ToList();
// do stuff with original list
}
I using Dynamic Linq to do some database queries and it's working really well up to now. I can pass a string to a Select to select fields like so:
var output = myDatabaseTable.Select("Foo, Bar");
For example. The power obviously being when you pass a string variable rather than hardcoded strings. The problem I'm running into now is that the library using IEnumerable instead of IEnumerable<T> because, obviously, it can't know T until runtime. I'm using this to select data and eventually return it to a client and it works fine for spitting out raw data, but now I want to be able to do some more processing before returning the data and that requires getting the query to run on the database first. I can do something like this:
var materializedResults = output.Cast<dynamic>().ToList();
And that will make the query run. But the problem is, once I've done that, it seems I can't use dynamic linq anymore. For example, if I did something like this:
var foos = materializedResults.Select("Foo");
I now get a System.Linq.Dynamic.ParseException with the message No property of field 'Foo' exists in type 'Object' (Note: I can see in the debugger that the materializedResults does actually have all the expected properties).
So after casting to a List so I can potentially iterate through it and modify some of the values, I can no longer query it.
So my question is, how can I take a dynamic query (with select, group by, order by etc provided as strings), materialize the results and then actually process those result dynamically?
I thought maybe if I could cast to the actual type rather than dynamic it might work, so I tried this:
var d = output.Cast<dynamic>().ToList();
MethodInfo method = typeof(Enumerable).GetMethod("Cast", new[] {typeof(IEnumerable)});
method = method.MakeGenericMethod(d.First().GetType());
output = method.Invoke(d, new[] {d}) as IEnumerable;
Which is ugly and requires me to cast twice. The first time to dynamic so I can get the type from the first item then again to that type.
If you do YourStuff.Cast<dynamic>.ToList(), you will receive IEnumerable<object>, and there is no property Foo on the type object.
The question you might be asking, how can you get IList<TheActualType>?! You can do it this way:
// for IEnumerable
public static IList ToAnonymousList(this IEnumerable enumerable)
{
var enumerator = enumerable.GetEnumerator();
if (!enumerator.MoveNext())
throw new Exception("?? No elements??");
var value = enumerator.Current;
var returnList = (IList) typeof (List<>)
.MakeGenericType(value.GetType())
.GetConstructor(Type.EmptyTypes)
.Invoke(null);
returnList.Add(value);
while (enumerator.MoveNext())
returnList.Add(enumerator.Current);
return returnList;
}
// for IQueryable
public static IList ToAnonymousList(this IQueryable source)
{
if (source == null) throw new ArgumentNullException("source");
var returnList = (IList) typeof (List<>)
.MakeGenericType(source.ElementType)
.GetConstructor(Type.EmptyTypes)
.Invoke(null);
foreach (var elem in source)
returnList.Add(elem);
return returnList;
}
It's a simple extension method that can later be used, as such:
var test = (new[]
{
new
{
Property1 = "10",
Property2 = "10",
Property3 = 1
}
}
.Select("New(Property1, Property2)"))
.ToAnonymousList();
Your Cast is Defaulting to which will cause an error
(output as System.Collections.Generics.IEnumerable)
This Cast Specified the Correct Interface Try again
(output as System.Collections.IEnumerable).Cast<dynamic>().ToList()
object selectedDataItem;
MyClass.Inventory inventory;
inventory = (MyClass.Inventory) selectedDataItem;
in inventory we can see the details such as:
Trace.Writeline(inventory.Name + " " + inventory.Place);
You see inventory has inventory.Name, Inventory.Place I want to wrap all of the property inside IEnumerable or ObservableCollection so that I can iterate through all of the inventory at once and not by inventory.Name, inventory.Place etc etc...
How can I make inventory IEnumerable so that I can do something like this :
IEnumerable<MyClass.Inventory> enumerable = (IEnumerable<MyClass.Inventory>) inventory;
enumerable = from x in enumerable where x.Name == inventory.Name select x;
Right now if I do this the error is
Unable to cast object of type 'MyClass.Inventory' to type 'System.Collections.Generic.IEnumerable`1[MyClass.Inventory]'.
Just do this:
var enumerable = new [] { inventory };
Not sure why do you need this, but once i saw next extension method:
public static class CustomExtensions
{
public static IEnumerable<T> ToEnumerable<T>(this T input)
{
yield return input;
}
}
inventory is an instance of class MyClass.Inventory and its not an enumerable list so that you can cast it directly. If you really want an enumerable with that object then you need to create an empty enumerable and add that object to it.
Update
You have to create a List first and add your object to that list, as,
List<MyClass.Inventory> lst = new List<MyClass.Inventory>();
lst.Add(inventory);
And then you can assign your list to the enumerable, as
IEnumerable<MyClass.Inventory> enumerable = lst;
reference
In general that would be a bad practice. If the data you're dealing with is not iterable, making it an IEnumerable makes no sense.
On the other hand, if you still want to use IEnumerable<T>, use List<T>, store your object in it, and then do the LINQ query!
I have a string representation of a type, and I need to get a list of that specific type. I am trying this:
var string_rep = "Double";
var list = _context.Entity.ToList<Type.GetType(string_rep)>();
I am getting "Operator < cannot be applied to operands of type method group and System.Type". What's the right way of doing it? Appreciate it.
Since there's no way of typing the list variable to the actual generic type of the list if that type isn't known until runtime, there's no real benefit to having the list strongly typed to begin with. You may as well just use:
var list = _context.Entity.ToList<object>();
There is no way for you to get any more compile-time support than from using that method.
While you can use reflection to create the list, for example by using:
public static IList ToList(this IEnumerable source, string typeName)
{
return ToList(source, Type.GetType(typeName));
}
public static IList ToList(this IEnumerable source, Type type)
{
var list = (IList)Activator.CreateInstance(
typeof(List<>).MakeGenericType(type));
foreach(object item in source) list.Add(item);
return list;
}
The only advantage that you would have using one of these two over the first example is that adding an item to the list that is not of the type specified would throw an exception, as opposed to allowing the list to contain any type of object. Usually this isn't important, but it may be better to have the exception right in your face over allowing items that shouldn't exist into the list.
You can use Reflection to do this at runtime. See the following post:
C# generic list <T> how to get the type of T?
I have a DAL method that returns an IEnumerable. I want a list of business objects, List<Person>. How do I build the list from the ienumerable return type ? When I inspect the return value in visual studio I see all the properties. i Just need to make the list.
thanks!
If the IEnumerable contains objects of a known type T, you can simply "convert" it to an IEnumerable<T> and then get a list using the ToList extension method:
IEnumerable foo; // obviously this needs to have a "real" value
var list = foo.Cast<T>().ToList();
Just use Enumerable<T>.ToList:
IEnumerable<T> source = // get data from some source;
List<T> list = source.ToList();
Alternatively, there is an overload of List<T> constructor that takes an IEnumerable<T>:
IEnumerable<T> source = // get data from source;
List<T> list = new List<T>(source);
or
List<T> list = new List<T>(// get data from source);
new List<Person>(MyMethod())
You can use the .ToList() when getting the results. Like this:
List<Person> lstPerson = DAL.GetPersonList().ToList();