Можно ли улучшить этот метод расширения? - PullRequest
1 голос
/ 29 апреля 2010

У меня есть следующий метод расширения

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 ]

3 голосов
/ 29 апреля 2010

Использование отражения таким образом для меня безобразно.

Вы уверены, что нуждаетесь в 100% универсальном "T" и не можете использовать базовый класс или интерфейс?

На вашем месте я бы хотел использовать метод .Where<T>(Func<T, Boolean>) LINQ вместо написания вашей собственной функции поиска.

Пример использования:

List<FactorClass> listFC1 = listFC.Where(fc => fc.Name == "BKP").ToList();
2 голосов
/ 29 апреля 2010
     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;
             }
            }
    } 
1 голос
/ 29 апреля 2010

Есть пара вещей, которые вы могли бы сделать - сначала вы можете наложить ограничение на универсальный тип для интерфейса, который имеет свойство 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 является лучшим решением этой проблемы.

1 голос
/ 29 апреля 2010

Просто получите тип Т

        Type k = typeof(T);
        PropertyInfo pi = k.GetProperty("Name");
        foreach (T t in collection)
        {                
            if (pi.GetValue(t, null).Equals(stringToSearch))
            {
                yield return t;
            }
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...