gpt4 book ai didi

c# - ((IEnumerable)source).OfType() 和 source as IEnumerable 之间有什么区别

转载 作者:太空狗 更新时间:2023-10-30 00:03:55 25 4
gpt4 key购买 nike

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

在另一个地方我创建了 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;
}

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

这里是 MapAndCreateSubList 方法和 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");
};

最佳答案

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

你是对的。它们非常不同。

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

后者的意思是“如果源序列的运行时类型是给定的类型,则给我一个对该序列的引用,否则给我 null”。

我举个例子。假设你有:

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

这会给你一个新的、不同的序列,其中包含一只老虎。

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

那会给你 null。动物不是哺乳动物的序列,尽管它是碰巧只是哺乳动物的动物序列。动物的实际运行时类型是“动物数组”,动物数组与哺乳动物序列不类型兼容。为什么不?好吧,假设转换成功了,然后你说:

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

嘿,你只是将一条蛇放入一个只能包含哺乳动物的变量中!我们不允许这样做,因此转换不起作用。

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

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

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

但要理解的关键是 OfType<T>方法返回一个全新的序列,“as”运算符执行运行时类型测试。这些是完全不同的事情。

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

tigers = animals.OfType<Tiger>()

基本一样
tigers = animals.Where(x=>x is Tiger).Select(x=>(Tiger)x);

也就是说,通过对动物的每个成员进行测试,看它是否是老虎,从而产生一个新的序列。如果是,投它。如果不是,请丢弃它。

mammals = animals as IEnumerable<Mammal>另一方面,与

基本相同
if (animals is IEnumerable<Mammal>)
mammals = (IEnumerable<Mammal>) animals;
else
mammals = null;

有道理吗?

关于c# - ((IEnumerable)source).OfType<T>() 和 source as IEnumerable<T> 之间有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3739319/

25 4 0