这种扩展方法可以改进吗?

时间:2010-04-29 03:08:37

标签: c#-3.0

我有以下扩展方法

public static class ListExtensions
    {

        public static IEnumerable<T> Search<T>(this ICollection<T> collection, string stringToSearch)
        {
            foreach (T t in collection)
            {
                Type k = t.GetType();
                PropertyInfo pi = k.GetProperty("Name");
                if (pi.GetValue(t, null).Equals(stringToSearch))
                {
                    yield return t;
                }
            }
        } 

    }

它的作用是使用反射,它找到name属性,然后根据匹配的字符串过滤集合中的记录。

此方法被称为

List<FactorClass> listFC = new List<FactorClass>();
    listFC.Add(new FactorClass { Name = "BKP", FactorValue="Book to price",IsGlobal =false  });
    listFC.Add(new FactorClass { Name = "YLD", FactorValue = "Dividend yield", IsGlobal = false });
    listFC.Add(new FactorClass { Name = "EPM", FactorValue = "emp", IsGlobal = false });
    listFC.Add(new FactorClass { Name = "SE", FactorValue = "something else", IsGlobal = false });    
   List<FactorClass> listFC1 = listFC.Search("BKP").ToList();

工作正常。

但仔细研究一下扩展方法就会发现

Type k = t.GetType();
PropertyInfo pi = k.GetProperty("Name");

实际上是在foreach循环中,实际上并不需要。我想我们可以把它带到循环之外。

但是怎么样?

提供帮助。 (C#3.0)

4 个答案:

答案 0 :(得分:3)

以这种方式使用反射对我来说很难看。

您确定需要100%通用的“T”并且不能使用基类或接口吗?

如果我是你,我会考虑使用.Where<T>(Func<T, Boolean>) LINQ方法而不是编写自己的搜索功能。

示例用法是:

List<FactorClass> listFC1 = listFC.Where(fc => fc.Name == "BKP").ToList();

答案 1 :(得分:2)

     public static IEnumerable<T> Search<T>(this ICollection<T> collection, string stringToSearch)
    {

            Type k = typeof(T);
            PropertyInfo pi = k.GetProperty("Name");

            foreach (T t in collection)
            {
             if (pi.GetValue(t, null).Equals(stringToSearch))
             {
                yield return t;
             }
            }
    } 

答案 2 :(得分:1)

得到T的类型

        Type k = typeof(T);
        PropertyInfo pi = k.GetProperty("Name");
        foreach (T t in collection)
        {                
            if (pi.GetValue(t, null).Equals(stringToSearch))
            {
                yield return t;
            }
        }

答案 3 :(得分:1)

您可以执行以下操作 - 首先,您可以将泛型类型的约束设置为具有name属性的接口。如果它只能使用FactorClass,那么您实际上并不需要泛型类型 - 您可以将其作为ICollection<FactorClass>的扩展。如果您使用接口路由(或使用非泛型版本),则只需引用该属性即可,无需进行反射。如果由于某种原因,这不起作用,你可以这样做:

 var k = typeof(T);
 var pi = k.GetProperty("Name");
 foreach (T t in collection)  
 {   
      if (pi.GetValue(t, null).Equals(stringToSearch))  
      {  
           yield return t;  
      }
 }  

使用界面可能看起来像

 public static IEnumerable<T> Search<T>(this ICollection<T> collection, string stringToSearch) where T : INameable
 {   
    foreach (T t in collection)   
    {      
        if (string.Equals( t.Name, stringToSearch))   
        {   
            yield return t;   
        }   
    }
 }

编辑:在看到@ Jeff的评论之后,如果您正在做一些比简单地检查其中一个属性的值更复杂的事情,这真的很有用。他绝对正确,使用Where是解决该问题的更好方法。