使用Type实例参数实现Enumerable.OfType <t>

时间:2016-10-06 14:39:03

标签: c# linq generics reflection types

我试图实现OfType的替代方法,您可以在其中指定所需类型作为Type实例参数,而不是使用类型参数化,但我不确定&#39;正确的方法&#39;实现它是。这就是我到目前为止所做的:

public static IEnumerable<T> OfType<T>(this IEnumerable<T> enumerable, Type type)
{
    return enumerable.Where(element => type.IsInstanceOfType(element));
}

我最初开始使用下面的代码,但意识到它不支持继承......

public static IEnumerable<T> OfType<T>(this IEnumerable<T> enumerable, Type type)
{
    return enumerable.Where(element => element.GetType() == type);
}

然后我想到比较基础类型几秒钟,然后才认为这可能是一个坏主意。

所以我的问题是,由于提供的类型相同,顶部的代码总是会返回与OfType相同的结果吗?换句话说,下面代码示例中的集合parametrizedFilteredtypeInstanceFiltered是否包含相同的元素,还是我要离开?

IEnumerable<InterfaceType> someCollection = BlackBox.GetCollection();
IEnumerable<DerivedType> parametrizedFiltered = someCollection.OfType<DerivedType>();
IEnumerable<InterfaceType> typeInstanceFiltered = someCollection.OfType(typeof(DerivedType));

1 个答案:

答案 0 :(得分:2)

如果您想知道您的实施是否会提供与Enumerable.OfType<>相同的结果,那么它会。

Enumerable.OfType<>使用is作为其实施,而is显示,Type.IsAssignableFrom()关键字将为IsInstanceOfType()提供相同的结果。

您需要的另一条信息是IsAssignableFrom是使用public virtual bool IsInstanceOfType(Object o) { if (o == null) return false; // No need for transparent proxy casting check here // because it never returns true for a non-rutnime type. return IsAssignableFrom(o.GetType()); } 实现的:

Demo.Base
Demo.Derived

下面的测试代码将打印

using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    public class Base {}
    public class Derived : Base {}

    class Program
    {
        static void Main()
        {
            object[] array = {"String", new Base(), new Derived(), 12345};

            foreach (var item in OfType(array, typeof(Base)))
                Console.WriteLine(item);
        }

        public static IEnumerable<T> OfType<T>(IEnumerable<T> enumerable, Type type)
        {
            return enumerable.Where(element => type.IsInstanceOfType(element));
        }
    }
}

表明您的原始代码确实可以使用继承:

IsInstanceOfType()

请注意,因为IsAssignableFrom是使用public static IEnumerable<T> OfType<T>(this IEnumerable<T> enumerable, Type type) { return enumerable.Where(element => type.IsAssignableFrom(element.GetType())); } 实现的,所以您可以像这样编写您的方法:

class Customer::CartsController < ApplicationController
  before_action :authenticate_user!
  def show
      if current_user
    if current_user.cart.purchased_at
        session[:cart_id] = nil
    else
    @cart = current_user.cart ||= Cart.find_by(session[:cart_id])
    end 
end
if session[:cart_id].nil?
    current_user.cart = Cart.create!(user_id: params[:id])
    session[:cart_id] = current_user.cart.id 
end
@cart = current_user.cart
end