((IEnumerable)source).OfType() 和 source as IEnumerable之间有什么区别?
((IEnumerable)source).OfType
和 source as IEnumerable
对我来说它们看起来很相似,但事实并非如此!
source
的类型为 IEnumerable
,但它被装箱为 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方法和地图代表:
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!
source
is of type IEnumerable<T>
, but it is boxed as an object
.
Edit
Here is some 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; }
}
On another place 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 anyone can tell me why I have to cast the mappedList to object, I would be really thankful :)
And here 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");
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你是对的。他们非常不同。
前者的意思是“获取源序列并生成一个全新的、不同的序列,该序列由前一个序列中给定类型的所有元素组成”。
后者意味着“如果源序列的运行时类型是给定类型,则给我对该序列的引用,否则给我 null”。
让我用一个例子来说明。假设你有:
这会给你一个新的、不同的序列,其中包含一只老虎。
那会给你 null 。动物不是哺乳动物的序列,尽管它是恰好只是哺乳动物的动物序列。动物的实际运行时类型是“动物数组”,并且动物数组与哺乳动物序列类型不兼容。为什么不呢?好吧,假设转换成功了,然后你说:
嘿,你只需将蛇放入只能包含哺乳动物的变量中!我们不能允许这种情况发生,因此转换不起作用。
在 C# 4 中,您可以走另一条路。您可以这样做:
因为动物数组可以被视为对象序列。你把一条蛇放在那里,蛇仍然是一个物体。但这仅适用于 C# 4。 (只有当这两种类型都是引用类型时,它才有效。您不能将 int 数组转换为对象序列。)
但要理解的关键是
OfType;
方法返回一个全新的序列,并且“as”运算符执行运行时类型测试。这些是完全不同的事情。这是另一种看待它的方式。
tigers = Animals.OfType()
基本相同,即通过对动物的每个成员进行测试来查看它是否是老虎来生成新序列。如果是,则投射它。如果不是,请将其丢弃。
另一方面,基本相同
mammals = Animals as IEnumerable
与 IEnumerable有意义吗?
You are right. They are very different.
The former means "take the source sequence and produce a brand new, different sequence composed of all the elements of the given type from the previous sequence".
The latter means "if the runtime type of the source sequence is of the given type then give me a reference to that sequence, otherwise give me null".
Let me illustrate with an example. Suppose you have:
That will give you back a new, different sequence that contains a single tiger.
That will give you null. Animals is NOT a sequence of mammals, even though it is a sequence of animals that happen to only be mammals. The actual runtime type of animals is "array of animal" and an array of animals is not type-compatible with a sequence of mammals. Why not? Well, suppose the conversion worked, and you then said:
And hey, you just put a snake into a variable that can only contain a mammal! We cannot allow that, so the conversion does not work.
In C# 4 you can go the other way. You can do this:
because an array of animals can be treated as a sequence of objects. You put a snake in there, and a snake is still an object. This only works in C# 4 though. (And it only works if the two types are both reference types. You cannot turn an array of int into a sequence of object.)
But the key thing to understand is that the
OfType<T>
method returns a brand-new sequence, and the "as" operator does a runtime type test. Those are completely different things.Here's another way to look at it.
tigers = animals.OfType<Tiger>()
is basically the same asThat is, produce a new sequence by doing a test of each member of animals to see if it is a tiger. If it is, cast it. If it is not, discard it.
mammals = animals as IEnumerable<Mammal>
on the other hand, is basically the same asMake sense?
OfType()
只会返回枚举中 T 类型的类型。因此,如果您有此then 调用
,那么 myStrings 将是一个可枚举的值,它将跳过 1 和 2,只返回您“嗨”和“那里”。您无法将 myObjects 转换为
IEnumerable
,因为事实并非如此。此处类似的另一个运算符是
Cast()
,它将尝试将所有项目强制转换为 T 类型。在这种情况下,一旦开始迭代 myStrings,您将得到一个 < code>InvalidCastException,因为它会尝试将 1 转换为字符串并失败。
OfType<T>()
will only return the types inside the enumeration that are of type T. So if you have thisThen call
Then myStrings will be an enumerable that will skip 1 and 2 and only return you "hi" and "there". You can't cast myObjects to
IEnumerable<string>
, because that's not what it is.The other operator that is similar here is
Cast<T>()
, which will attempt to cast all of the items to type T.Once you start iterating over myStrings in this case, you will get a
InvalidCastException
, because it will try to cast 1 to a string and fail.