((IEnumerable)source).OfType <T>()和作为IEnumerable <T>的源有什么区别

Roo*_*ian 4 c# linq ienumerable boxing casting

((IEnumerable)source).OfType<T>()和之间有什么区别source as IEnumerable<T>

对我来说,他们看起来很相似,但他们不是!

source是类型IEnumerable<T>,但它被装箱为object.

编辑

这是一些代码:

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; }
}
Run Code Online (Sandbox Code Playgroud)

在另一个地方,我创建了一个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;
}
Run Code Online (Sandbox Code Playgroud)

如果有人能告诉我为什么我必须将mappedList转换为对象,我会非常感激:)

这里是MapAndCreateSubList方法和Map委托:

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");
};
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 12

有什么区别((IEnumerable)source).OfType<T>()source as IEnumerable<T>对我来说他们看起来很相似,但他们不是!

你是对的.他们是非常不同的.

前者的意思是"获取源序列并产生一个全新的,不同的序列,该序列由前一序列中给定类型的所有元素组成".

后者意味着"如果源序列的运行时类型是给定类型,那么给我一个对该序列的引用,否则给我null".

让我举一个例子来说明.假设你有:

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

这会让你回到一个包含一只老虎的新的不同序列.

IEnumerable<Mammal> mammals = animals as IEnumerable<Mammal>;
Run Code Online (Sandbox Code Playgroud)

这会给你null.动物不是哺乳动物的序列,即使它是一系列恰好只是哺乳动物的动物.动物的实际运行时类型是"动物阵列",并且一系列动物与哺乳动物序列不是类型相容的.为什么不?好吧,假设转换有效,然后你说:

animals[0] = snake;
Mammal mammal = mammals.First();
Run Code Online (Sandbox Code Playgroud)

嘿,你只是把蛇放进一个只能包含哺乳动物的变量中!我们不能允许,因此转换不起作用.

在C#4中你可以走另一条路.你可以这样做:

IEnumerable<Object> objects = animals as IEnumerable<Object>;
Run Code Online (Sandbox Code Playgroud)

因为一系列动物可以被视为一系列物体.你把蛇放在那里,蛇仍然是一个物体.这仅适用于C#4.(并且只有当两种类型都是引用类型时它才有效.您不能将int数组转换为对象序列.)

但要理解的关键是该OfType<T>方法返回一个全新的序列,"as"运算符执行运行时类型测试.那些是完全不同的东西.

这是另一种看待它的方式.

tigers = animals.OfType<Tiger>() 基本上是一样的

tigers = animals.Where(x=>x is Tiger).Select(x=>(Tiger)x);
Run Code Online (Sandbox Code Playgroud)

也就是说,通过对每个动物成员进行测试以确定它是否是老虎来产生新的序列.如果是的话,投下它.如果不是,请丢弃它.

mammals = animals as IEnumerable<Mammal> 另一方面,基本上是一样的

if (animals is IEnumerable<Mammal>)
    mammals = (IEnumerable<Mammal>) animals;
else
    mammals = null;
Run Code Online (Sandbox Code Playgroud)

合理?