Linq возвращает объект списка или отдельный объект

Foo::new(words).split_first() будет интерпретироваться примерно как

let tmp = Foo::new(words);
let ret = tmp.split_first();
drop(tmp);
ret

Если бы Rust позволил вам сделать это, ссылки в ret указали бы s> [править: разрешено типом split_first указывать *] на теперь упавшее значение tmp. Так что хорошо, что Руст запрещает это. Если бы вы написали эквивалентную однострочную версию в C ++, вы бы молча получили неопределенное поведение.

Написав let привязку самостоятельно, вы задерживаете отбрасывание до конца области действия, расширяя тем самым область, где эти ссылки безопасны.

Подробнее см. временные времена жизни в справочнике по ржавчине.

* Редактировать: Как указал Jmb , реальная проблема в этом конкретном примере заключается в том, что тип

fn split_first(&'a self) -> &'a str

недостаточно конкретен, и лучшим решением является уточните тип до:

fn split_first<'b>(&'b self) -> &'a str

, что может быть сокращено:

fn split_first(&self) -> &'a str

Это передает предполагаемую гарантию того, что возвращаемые ссылки не указывают на Foo<'a> (только на строку сам по себе).

7
задан Nelson Reis 1 April 2010 в 09:36
поделиться

7 ответов

Править: На основе Вашего обновления ошибка может быть связана с перечислением в Вашем классе объекта. См. эту запись в блоге для получения дополнительной информации и обходное решение. Я оставляю свой исходный ответ как улучшение на Вашем синтаксисе запроса.

Попытайтесь делать выбор первого объекта в самом запросе с помощью FirstOrDefault и затем проверьте, является ли результат пустым.

int compareCategory = (int)pCategory; // just a guess
var result = (from r in entities.MachineRevision
              where r.Machine.IdMachine == pIdMachine
                 && r.Category == compareCategory
              select r).FirstOrDefault();

if (result != null)
{
     return new oMachineRevision(result.IdMachineRevision);
}
11
ответ дан 6 December 2019 в 11:53
поделиться

Почему не только используют FirstOrDefault () и проверяют на пустой указатель? Я не вижу преимущества в запросах для количества и затем взятии первого элемента.

2
ответ дан 6 December 2019 в 11:53
поделиться

В стандартной реализации linq операторы "выбирают" и "где" карта к методам, которые возвращают IEnumerable или IQueryable. Столь стандартные linq методы при использовании должны всегда возвращать IEnumerable из запроса ни один объект.

Но методы linq, которые являются кандидатами на linq операторы, не ограничиваются методами, возвращая IEnumerables, любой метод, возвращая что-либо может быть выбран.

В случае, если у Вас есть методы экземпляра под названием "Выбор" и "Где" тот возврат отдельный объект или методы расширений, которые характерны для Вашего класса и возвращают отдельный объект, они будут использоваться вместо стандарта linq.

Мое предположение - то, что или "Выбор" или "Где" метод, определенный в Вашем классе, заставляет linq возвратить единственное значение вместо a IEnumerable<T>.

2
ответ дан 6 December 2019 в 11:53
поделиться

Я не знал, что различные анонимные объекты будут созданы в зависимости от результата запроса. Я предполагаю, что они просто хотели, чтобы результаты имели тип IEnumerable

Как насчет того, чтобы использовать foreach?

var results = from r in entities.MachineRevision
              where r.Machine.IdMachine == pIdMachine
                 && r.Category == pCategory
              select r;

foreach( var r in results )
{
    yield return new oMachineRevision( r.IdMachineRevision );
}
1
ответ дан 6 December 2019 в 11:53
поделиться

попытайтесь использовать

IENumerable<MachineRevision> results = from r in entities.MachineRevision
...

вместо этого.

Я думаю, что это - var, это вызывает Вашу проблему.

0
ответ дан 6 December 2019 в 11:53
поделиться

Править:

Прочитайте сообщение об ошибке. "Не удалось создать постоянную стоимость типа 'Тип закрытия'. Только типы примитивов ('такие как Int32, Строка и Гуид') поддерживаются в этом контексте".

Одно из этих сравнений с типом, который не является интервалом, строкой или гуидом. Я предполагаю Категорию.

r.Machine.IdMachine == pIdMachine && r.Category == pCategory

Интересно, LinqToSql позволит эту конструкцию. Не знайте, почему LinqToEntities не поддерживает это.

0
ответ дан 6 December 2019 в 11:53
поделиться

Думаю, вы также можете выбрать нужный элемент другим, более простым способом, используя лямбда-выражения.

var result = entities.MachineRevision
                 .Where(x => x.Machine.IdMachine == pIdMachine)
                 .Where(y => y.Category == (int)pCategory)
                 .FirstOrDefault();

if (result != null)
{
     return new oMachineRevision(result.IdMachineRevision);
}

, а затем действуя как обычно

0
ответ дан 6 December 2019 в 11:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: