((IEnumerable)source).OfType() 和 source as IEnumerable之间有什么区别?

发布于 2024-09-24 02:34:49 字数 2509 浏览 8 评论 0原文

((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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

九歌凝 2024-10-01 02:34:49

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

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

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

后者意味着“如果源序列的运行时类型是给定类型,则给我对该序列的引用,否则给我 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; 方法返回一个全新的序列,并且“as”运算符执行运行时类型测试。这些是完全不同的事情。

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

tigers = Animals.OfType() 基本相同

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

,即通过对动物的每个成员进行测试来查看它是否是老虎来生成新序列。如果是,则投射它。如果不是,请将其丢弃。

另一方面,mammals = Animals as IEnumerable 与 IEnumerable基本相同

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

有意义吗?

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

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:

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

That will give you back a new, different sequence that contains a single tiger.

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

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:

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

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:

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

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 as

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

That 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 as

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

Make sense?

度的依靠╰つ 2024-10-01 02:34:49

OfType() 只会返回枚举中 T 类型的类型。因此,如果您有此

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

then 调用

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

,那么 myStrings 将是一个可枚举的值,它将跳过 1 和 2,只返回您“嗨”和“那里”。您无法将 myObjects 转换为 IEnumerable,因为事实并非如此。

此处类似的另一个运算符是 Cast(),它将尝试将所有项目强制转换为 T 类型。

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

在这种情况下,一旦开始迭代 myStrings,您将得到一个 < code>InvalidCastException,因为它会尝试将 1 转换为字符串并失败。

OfType<T>() will only return the types inside the enumeration that are 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 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.

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文