What is the difference between ((IEnumerable) source) .OfType <T> () and source as IEnumerable <T>

What is the difference between ((IEnumerable)source).OfType<T>() and source as IEnumerable<T>

For me they are similar, but they are not!

source is of type IEnumerable<T> , but it is placed as an object .

Edit

Here is the code:

 public class PagedList<T> : List<T>, IPagedList { public PagedList(object source, int index, int pageSize, int totalCount) { if (source == null) throw new ArgumentNullException("The source is null!"); // as IEnumerable<T> gives me only null IEnumerable<T> list = ((IEnumerable)source).OfType<T>(); if (list == null) throw new ArgumentException(String.Format("The source is not of type {0}, the type is {1}", typeof(T).Name, source.GetType().Name)); PagerInfo = new PagerInfo { TotalCount = totalCount, PageSize = pageSize, PageIndex = index, TotalPages = totalCount / pageSize }; if (PagerInfo.TotalCount % pageSize > 0) PagerInfo.TotalPages++; AddRange(list); } public PagerInfo PagerInfo { get; set; } } 

Elsewhere I create an instance of PagedList

 public static object MapToPagedList<TSource, TDestination>(TSource model, int page, int pageSize, int totalCount) where TSource : IEnumerable { var viewModelDestinationType = typeof(TDestination); var viewModelDestinationGenericType = viewModelDestinationType.GetGenericArguments().FirstOrDefault(); var mappedList = MapAndCreateSubList(model, viewModelDestinationGenericType); Type listT = typeof(PagedList<>).MakeGenericType(new[] { viewModelDestinationGenericType }); object list = Activator.CreateInstance(listT, new[] { (object) mappedList, page, pageSize, totalCount }); return list; } 

If someone tells me why I should use the mapping object for the object, I would be very grateful :)

And here is the MapAndCreateSubList method and the map delegate:

 private static List<object> MapAndCreateSubList(IEnumerable model, Type destinationType) { return (from object obj in model select Map(obj, obj.GetType(), destinationType)).ToList(); } public static Func<object, Type, Type, object> Map = (a, b, c) => { throw new InvalidOperationException( "The Mapping function must be set on the AutoMapperResult class"); }; 
+4
source share
2 answers

What is the difference between ((IEnumerable)source).OfType<T>() and source as IEnumerable<T> They are similar to me, but they are not!

You're right. They are very different.

The first means "take the original sequence and create a completely new, different sequence, consisting of all the elements of this type from the previous sequence."

The latter means "if the runtime type of the source sequence is of this type, then give me a link to this sequence, otherwise give me null."

Let me illustrate an example. Suppose you have:

 IEnumerable<Animal> animals = new Animal[] { giraffe, tiger }; IEnumerable<Tiger> tigers = animals.OfType<Tiger>(); 

This will give you a new, new sequence containing one tiger.

 IEnumerable<Mammal> mammals = animals as IEnumerable<Mammal>; 

This will give you a null value. Animals are not a sequence of mammals, although this is a sequence of animals, which, apparently, are only mammals. The actual type of animal lifespan is an “array of animals”, and the array of animals is not compatible with the type of sequence of mammals. Why not? Well, suppose the conversion worked, and you said:

 animals[0] = snake; Mammal mammal = mammals.First(); 

And hey, you just put the snake in a variable that can only contain a mammal! We cannot allow this, so the conversion does not work.

In C # 4, you can go the other way. You can do it:

 IEnumerable<Object> objects = animals as IEnumerable<Object>; 

because an array of animals can be considered as a sequence of objects. You put a snake there, and the snake is still an object. This only works in C # 4. (And it only works if both types are reference types. You cannot turn an int array into a sequence of objects.)

But the main thing is to understand that the OfType<T> method returns a completely new sequence, and the "as" operator performs a run-time type test. These are completely different things.

Here is another way to look at it.

tigers = animals.OfType<Tiger>() basically matches

 tigers = animals.Where(x=>x is Tiger).Select(x=>(Tiger)x); 

That is, create a new sequence by performing a test on each animal member to make sure it is a tiger. If so, drop it. If it is not, drop it.

mammals = animals as IEnumerable<Mammal> , on the other hand, is basically the same as

 if (animals is IEnumerable<Mammal>) mammals = (IEnumerable<Mammal>) animals; else mammals = null; 

Make sense?

+12
source

OfType<T>() will return types inside an enumeration of type T. So if you have this

 object[] myObjects = new object[] { 1, 2, "hi", "there" }; 

Then call

 var myStrings = myObjects.OfType<string>(); 

Then myStrings will be enumerated, which will skip 1 and 2 and return you "hello" and "there." You cannot use myObjects for IEnumerable<string> because it is not what it is.

Another operator similar here is Cast<T>() , which will try to display all the elements for input T.

  var myStrings = myObjects.Cast<string>(); 

As soon as you start looping through myStrings in this case, you will get an InvalidCastException because it will try to pass 1 to the string and fail.

+3
source

All Articles