2010-06-01 3 views
0

Вот мир коды:оптимизация LinQ

void MyFunc(List<MyObj> objects) 
{ 
    MyFunc1(objects); 

    foreach(MyObj obj in objects.Where(obj1=>obj1.Good)) 
    { 
    // Do Action With Good Object 
    } 
} 

void MyFunc1(List<MyObj> objects) 
{ 
    int iGoodCount = objects.Where(obj1=>obj1.Good).Count(); 
    BeHappy(iGoodCount); 

    // do other stuff with 'objects' collection 
} 

Здесь мы видим, что коллекция анализируются дважды, и каждый раз, когда значение «Good» имущества проверяются для каждого члена: первый раз при расчете количества хорошего объекты, 2-й - при повторении всех хороших объектов.

Желательно иметь, что оптимизируется, и здесь является простым решением:

  • перед вызовом в MyFunc1 makecreate дополнительную временную коллекцию хороших объектов только (goodObjects, это может быть IEnumerable);
  • получить количество этих объектов и передать его как дополнительный параметр MyFunc1;
  • в методе «MyFunc» перебираем не через объекты object.Where (...) », а через коллекцию« goodObjects ».

Не слишком плохой подход (насколько я вижу), но требуется дополнительная переменная, которая должна быть создана в методе «MyFunc», и требуется дополнительный параметр.

Вопрос: есть ли какие-либо функциональные возможности LinQ, позволяющие выполнять кеширование во время 1-го Where(). Count(), помня о обработанной коллекции и использовать ее на следующей итерации?

Любые мысли приветствуются.

Спасибо.

ответ

2

Нет, запросы LINQ не оптимизированы таким образом (то, что вы описываете, похоже на то, как SQL Server повторно использует план выполнения запроса). LINQ не (и для практических целей не может) достаточно знать о ваших объектах, чтобы оптимизировать этот способ. Насколько известно, ваша коллекция изменилась (или совсем другая) между двумя вызовами.

Очевидно, что вы сохраняете свой запрос в новом List<T>, но кроме того, я ничего не могу порекомендовать, не зная больше о вашем классе и где еще используется MyFunc.

+0

В любом случае, спасибо вам за разъяснения. – Budda

0

Пока MyFunc1 не нуждается в изменении списка путем добавления/удаления объектов, это будет работать.

void MyFunc(List<MyObj> objects) 
{ 
    ILookup<bool, MyObj> objLookup = objects.ToLookup(obj1 => obj1.Good); 
    MyFunc1(objLookup[true]); 

    foreach(MyObj obj in objLookup[true]) 
    { 
    //.. 
    } 
} 

void MyFunc1(IEnumerable<MyObj> objects) 
{ 
    //.. 
} 
Смежные вопросы