2

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?

Bagzli
  • 6,254
  • 17
  • 80
  • 163
  • 6
    `var list = temp.ToList();` –  Mar 22 '16 at 21:13
  • 4
    Because your `IEnumerable` is not a `List`. `IEnumerable`s come in many shapes and sizes, and many of them are not `List`s. Try using `.ToList()` instead. – Glorin Oakenfoot Mar 22 '16 at 21:13
  • Don't use `as` to cast in C#. Use `(List)temp` unless you want `list` to be `null` if `temp` is not a `List`. – Jacob Krall Mar 22 '16 at 21:48
  • Please see this [previous question on SO](http://stackoverflow.com/a/2033921/1260204) and also [Covariance and Contravariance](https://msdn.microsoft.com/en-us/library/ee207183.aspx). Also make sure that `MyObject` actually implements `IMyObject` and that the instances returned in the list are all of concrete type `MyObject`. – Igor Mar 23 '16 at 13:43
  • Why don't you just return an `IEnumerable` ? There is no reason to return a `List` in that method. – Jamie Rees Mar 24 '16 at 17:26

2 Answers2

4

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.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • the problem of when I do .ToList is that it wanst `List` as return type and I need to serialize the object. I can't seem to serialize it the object if I return it like that. – Bagzli Mar 22 '16 at 21:20
  • 2
    @Bagzli Then just use the `List` constructor. – Servy Mar 22 '16 at 21:25
3

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;
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • IEnumerable already implements ToList(). It will infer the generic type as a list of T, so, there is no need of doing this unless MyObject is inherited from the generic class – Octanic Mar 24 '16 at 17:41
  • @Octanic IEnumerable does not implement ToList(). https://msdn.microsoft.com/en-us/library/system.collections.ienumerable%28v=vs.110%29.aspx – Nkosi Mar 24 '16 at 17:49
  • Indeed, I should've refer it as IEnumerable... Check this out: https://msdn.microsoft.com/en-us/library/9eekhta0(v=vs.110).aspx @Nkosi – Octanic Mar 24 '16 at 17:51
  • Those are extension methods. IEnumerable `Exposes the enumerator, which supports a simple iteration over a collection of a specified type.` as such it only had one method (single responsibility) `GetEnumerator()` – Nkosi Mar 24 '16 at 17:59
  • Yes, but practically speaking, it is not necessary to use cast or oftype just to perform tolist. @Nkosi – Octanic Mar 24 '16 at 18:02
  • The OP stated that repository.GetData returns IEnumerable. note the `IMyObject` Interface. the OfType and/or Cast is to convert the interface to the concrete type `MyObject` – Nkosi Mar 24 '16 at 18:05
  • if you call ToList on `IEnumerable` while the method is suppose to return IList you get a type mismatch. hence the conversion. – Nkosi Mar 24 '16 at 18:06
  • That's correct. I've missed the "I" on the myobject, so, that's a good solution! Thanks for the patience explaining this! – Octanic Mar 24 '16 at 18:08