Действительно Классифицирует потребность реализовать IEnumerable для использования Foreach

Laravel предлагает whereJsonContains , поэтому вы можете попробовать следующий код:

$resumes = UserMeta::with(['user.resume' => function ($query) {
                $query->whereJsonContains('data->section_4->type', 'like', '%education%');
        }])->paginate(10);

ИЛИ вы также можете использовать whereRaw с комбинацией [ 114] в этом случае:

например

whereRaw("JSON_CONTAINS(type, '[education]' )")->get();

Для получения дополнительной информации проверьте сообщение

15
задан ine 24 September 2008 в 13:52
поделиться

10 ответов

foreach делает не , требуют IEnumerable, вопреки широко распространенному мнению. Все, чего требуется, является методом GetEnumerator, который возвращает любой объект, который имеет метод MoveNext и получать-свойство Current с соответствующими подписями.

РЕДАКТИРОВАНИЕ/: В Вашем случае, однако, Вам не повезло. Можно тривиально перенести объект, однако, сделать это счетным:

class EnumerableWrapper {
    private readonly TheObjectType obj;

    public EnumerableWrapper(TheObjectType obj) {
        this.obj = obj;
    }

    public IEnumerator<YourType> GetEnumerator() {
        return obj.TheMethodReturningTheIEnumerator();
    }
}

// Called like this:

foreach (var xyz in new EnumerableWrapper(yourObj))
    …;

РЕДАКТИРОВАНИЕ/: следующий метод, предложенный несколькими людьми, делает не работа, если метод возвращается IEnumerator:

foreach (var yz in yourObj.MethodA())
    …;
15
ответ дан 1 December 2019 в 01:17
поделиться

Чтобы класс был применим с foeach все, что он должен сделать, имеют открытый метод, который возвращается и IEnumerator под названием GetEnumerator (), вот именно:

Посещают следующий урок, он не реализует IEnumerable или IEnumerator:

public class Foo
{
    private int[] _someInts = { 1, 2, 3, 4, 5, 6 };
    public IEnumerator GetEnumerator()
    {
        foreach (var item in _someInts)
        {
            yield return item;
        }
    }
}

альтернативно GetEnumerator () метод мог быть записан:

    public IEnumerator GetEnumerator()
    {
        return _someInts.GetEnumerator();
    }

При использовании в foreach (Отмечают, что никакая обертка не используется, просто экземпляр класса):

    foreach (int item in new Foo())
    {
        Console.Write("{0,2}",item);
    }

печать:

1 2 3 4 5 6

0
ответ дан 1 December 2019 в 01:17
поделиться

Ре: Если foreach не требует явного интерфейсного контракта, он находит GetEnumerator с помощью отражения?

(я не могу прокомментировать, так как у меня нет достаточно высокой репутации.)

, Если Вы подразумеваете время выполнения отражение затем нет. Это делает все это время компиляции, другой менее известный факт - то, что это также проверяет, чтобы видеть, доступен ли возвращенный объект, который мог бы Реализация IEnumerator.

, Чтобы видеть, что это в действии рассматривает этот (выполнимый) отрывок.


using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication3
{
    class FakeIterator
    {
        int _count;

        public FakeIterator(int count)
        {
            _count = count;
        }
        public string Current { get { return "Hello World!"; } }
        public bool MoveNext()
        {
            if(_count-- > 0)
                return true;
            return false;
        }
    }

    class FakeCollection
    {
        public FakeIterator GetEnumerator() { return new FakeIterator(3); }
    }

    class Program
    {
        static void Main(string[] args)
        {
            foreach (string value in new FakeCollection())
                Console.WriteLine(value);
        }
    }
}
7
ответ дан 1 December 2019 в 01:17
поделиться

Согласно MSDN:

foreach (type identifier in expression) statement

, где выражение:

Объектный набор или выражение с массивами. Тип элемента набора должен быть конвертируемым к типу идентификатора. Не используйте выражение, которое оценивает к пустому указателю. Оценивает к типу, который реализует IEnumerable или тип, который объявляет метод GetEnumerator. В последнем случае GetEnumerator должен или возвратить тип, который реализует IEnumerator или объявляет все методы, определенные в IEnumerator.

6
ответ дан 1 December 2019 в 01:17
поделиться

Короткий ответ:

Вам нужен класс с методом, названным GetEnumerator, который возвращает IEnumerator, который Вы уже имеете. Достигните этого с простой оберткой:

class ForeachWrapper
{
  private IEnumerator _enumerator;

  public ForeachWrapper(Func<IEnumerator> enumerator)
  {
    _enumerator = enumerator;
  }

  public IEnumerator GetEnumerator()
  {
    return _enumerator();
  }
}

Использование:

foreach (var element in new ForeachWrapper(x => myClass.MyEnumerator()))
{
  ...
}

От Спецификация языка C#:

время компиляции, обрабатывая foreach оператора сначала определяет тип набора, тип перечислителя и тип элемента выражения. Это определение продолжается следующим образом:

  • , Если тип X выражения является типом массива затем, существует неявное ссылочное преобразование от X до Системы. Наборы. Интерфейс IEnumerable (так как Система. Массив реализует этот интерфейс). Типом набора является Система. Наборы. Интерфейс IEnumerable, типом перечислителя является Система. Наборы. Интерфейс IEnumerator и тип элемента являются типом элемента типа массива X.

  • Иначе, определите, имеет ли тип X соответствующий метод GetEnumerator:

    • Выполняют членский поиск на типе X с идентификатором GetEnumerator и никакие аргументы типа. Если членский поиск не производит соответствие, или он производит неоднозначность или производит соответствие, которое не является группой метода, проверьте на счетный интерфейс, как описано ниже. Рекомендуется, чтобы предупреждение было выдано, если членский поиск производит что-нибудь кроме группы метода или никакого соответствия.

    • Выполняют разрешение перегрузки с помощью получающейся группы метода и списка пустого аргумента. Если результаты разрешения перегрузки ни в каких применимых методах, результаты в неоднозначности или результаты в единственном лучшем методе, но том методе или статичны или не общедоступны, проверьте на счетный интерфейс, как описано ниже. Рекомендуется, чтобы предупреждение было выдано, если разрешение перегрузки производит что-нибудь кроме однозначного общедоступного метода экземпляра или никаких применимых методов.

    • , Если тип E возврата метода GetEnumerator не является классом, структурой или интерфейсным типом, ошибка производится, и никакие дальнейшие шаги не предприняты.

    • членский поиск выполняется на E с Текущим идентификатором и никакие аргументы типа. Если членский поиск не производит соответствия, результатом является ошибка, или результат - что-либо кроме общедоступного свойства экземпляра, которое разрешает читать, ошибка производится, и никакие дальнейшие шаги не предприняты.

    • членский поиск выполняется на E с идентификатором MoveNext и никакие аргументы типа. Если членский поиск не производит соответствия, результатом является ошибка, или результат - что-либо кроме группы метода, ошибка производится, и никакие дальнейшие шаги не предприняты.

    • разрешение Перегрузки выполняется на группе метода со списком пустого аргумента. Если результаты разрешения перегрузки ни в каких применимых методах, результаты в неоднозначности или результаты в единственном лучшем методе, но том методе или статичны или не общедоступны, или его тип возврата не является bool, ошибка производится, и никакие дальнейшие шаги не предприняты.

    • тип набора X, тип перечислителя является E, и тип элемента является типом свойства Current.

  • Иначе, проверьте на счетный интерфейс:

    • , Если существует точно один тип T, таким образом, что существует неявное преобразование от X до интерфейса System. Наборы. Универсальный. IEnumerable< T> затем тип набора является этим интерфейсом, тип перечислителя является интерфейсом System. Наборы. Универсальный. IEnumerator< T> и тип элемента является T.

    • Иначе, если существует больше чем один такой тип T, то ошибка производится и никакие дальнейшие шаги не предприняты.

    • Иначе, если существует неявное преобразование от X до Системы. Наборы. Интерфейс IEnumerable, затем тип набора является этим интерфейсом, тип перечислителя является интерфейсом System. Наборы. IEnumerator и тип элемента являются объектом.

    • Иначе, ошибка производится, и никакие дальнейшие шаги не предприняты.

4
ответ дан 1 December 2019 в 01:17
поделиться

Не строго. Пока класс имеет необходимый GetEnumerator, MoveNext, Сброс и текущие элементы, он будет работать с foreach

3
ответ дан 1 December 2019 в 01:17
поделиться

Нет, Вы не делаете и Вам даже не нужен метод GetEnumerator, например:

class Counter
{
    public IEnumerable<int> Count(int max)
    {
        int i = 0;
        while (i <= max)
        {
            yield return i;
            i++;
        }
        yield break;
    }
}

, который называют этим путем:

Counter cnt = new Counter();

foreach (var i in cnt.Count(6))
{
    Console.WriteLine(i);
}
2
ответ дан 1 December 2019 в 01:17
поделиться

Учитывая класс X с методами A и B, что оба возврата IEnumerable, Вы могли использовать foreach на классе как это:

foreach (object y in X.A())
{
    //...
}

// or

foreach (object y in X.B())
{
   //...
}

, По-видимому, значение для enumerables, возвращенного A и B, четко определено.

0
ответ дан 1 December 2019 в 01:17
поделиться

Вы могли всегда переносить его, и как в стороне, чтобы быть "foreachable" у Вас только должен быть метод под названием "GetEnumerator" с надлежащей подписью.


class EnumerableAdapter
{
  ExternalSillyClass _target;

  public EnumerableAdapter(ExternalSillyClass target)
  {
    _target = target;
  }

  public IEnumerable GetEnumerator(){ return _target.SomeMethodThatGivesAnEnumerator(); }

}
0
ответ дан 1 December 2019 в 01:17
поделиться

@Brian: Не уверенный Вы пытаетесь циклично выполниться по возврату значения из вызова метода или самого класса, Если то, что Вы хотите, является классом затем, делают это массивом, который можно использовать с foreach.

0
ответ дан 1 December 2019 в 01:17
поделиться
Другие вопросы по тегам:

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