LINQ: "содержит" и Лямбда-запрос

У меня есть список, который содержит перечисления. Он является стандартным Enum, но имеет прикрепленный к нему атрибут и метод расширения, который возвращает CHAR перечисления (см. Ниже - GetCharValue); расширение работает отлично.

Теперь у меня есть (другой метод расширения для LINQ)

public static IQueryable<Building> WithStatus(this IQueryable<Building> qry, 
         IList<BuildingStatuses> buildingStatus)
{
    return from v in qry
           where buildingStatus.Where(item => item.GetCharValue() == 
           v.Status)
           select v;
}

Мне в основном нужно сказать "Возвратить" все в запросе, но только если v.Status находится в buildStatus... но помните, что buildStatus - это ILIST перечислений, поэтому я ДОЛЖЕН вызвать GetCharValue.

У меня была некоторая помощь, прежде чем я подумал, что правильный синтаксис

buildingStatus.Contains (v.Status)   

но проблема в том, что buildingStatus - это список из списков Enum, поэтому я должен вызвать GetCharValue() для каждого элемента в списке Ilist, прежде чем говорить "Содержит".

Я думал, что есть что-то особенное, чтобы сделать это с помощью лямбда, используя Содержит - так, конечно, это не работает.

where buildingStatus.Contains(item => item.GetCharValue() == v.Status)

Может ли кто-нибудь помочь?

Ответ 1

Используйте Any() вместо Содержит:

buildingStatus.Any(item => item.GetCharValue() == v.Status)

Ответ 2

Метод расширения Linq Любой может работать для вас...

buildingStatus.Any(item => item.GetCharValue() == v.Status)

Ответ 3

Я не уверен точно, что вы ищете, но эта программа:

    public class Building
    {
        public enum StatusType
        {
            open,
            closed,
            weird,
        };

        public string Name { get; set; }
        public StatusType Status { get; set; }
    }

    public static List <Building> buildingList = new List<Building> ()
    {
        new Building () { Name = "one", Status = Building.StatusType.open },
        new Building () { Name = "two", Status = Building.StatusType.closed },
        new Building () { Name = "three", Status = Building.StatusType.weird },

        new Building () { Name = "four", Status = Building.StatusType.open },
        new Building () { Name = "five", Status = Building.StatusType.closed },
        new Building () { Name = "six", Status = Building.StatusType.weird },
    };

    static void Main (string [] args)
    {
        var statusList = new List<Building.StatusType> () { Building.StatusType.open, Building.StatusType.closed };

        var q = from building in buildingList
                where statusList.Contains (building.Status)
                select building;

        foreach ( var b in q )
            Console.WriteLine ("{0}: {1}", b.Name, b.Status);
    }

выводит ожидаемый результат:

one: open
two: closed
four: open
five: closed

Эта программа сравнивает строковое представление перечисления и производит тот же вывод:

    public class Building
    {
        public enum StatusType
        {
            open,
            closed,
            weird,
        };

        public string Name { get; set; }
        public string Status { get; set; }
    }

    public static List <Building> buildingList = new List<Building> ()
    {
        new Building () { Name = "one", Status = "open" },
        new Building () { Name = "two", Status = "closed" },
        new Building () { Name = "three", Status = "weird" },

        new Building () { Name = "four", Status = "open" },
        new Building () { Name = "five", Status = "closed" },
        new Building () { Name = "six", Status = "weird" },
    };

    static void Main (string [] args)
    {
        var statusList = new List<Building.StatusType> () { Building.StatusType.open, Building.StatusType.closed };
        var statusStringList = statusList.ConvertAll <string> (st => st.ToString ());

        var q = from building in buildingList
                where statusStringList.Contains (building.Status)
                select building;

        foreach ( var b in q )
            Console.WriteLine ("{0}: {1}", b.Name, b.Status);

        Console.ReadKey ();
    }

Я создал этот метод расширения для преобразования одного IEnumerable в другой, но я не уверен, насколько он эффективен; он может просто создать список за кулисами.

public static IEnumerable <TResult> ConvertEach (IEnumerable <TSource> sources, Func <TSource,TResult> convert)
{
    foreach ( TSource source in sources )
        yield return convert (source);
}

Затем вы можете изменить предложение where:

where statusList.ConvertEach <string> (status => status.GetCharValue()).
    Contains (v.Status)

и пропустите создание List<string> с ConvertAll () в начале.

Ответ 4

Если я правильно понял, вам нужно преобразовать тип (char), который вы храните в списке Строить список (перечисление), который вы храните в списке buildingStatus.

(Для каждого статуса в списке "Строй" //// значение//, статус имеет место в списке buildingStatus//значение перечисления // )

public static IQueryable<Building> WithStatus(this IQueryable<Building> qry,  
         IList<BuildingStatuses> buildingStatus) 
    { 
        return from v in qry 
               where ContainsStatus(v.Status)
               select v;         
    } 


private bool ContainsStatus(v.Status)
{
 foreach(Enum value in Enum.GetValues(typeof(buildingStatus)))
 {
  If v.Status == value.GetCharValue();
   return true;
 }
 return false;
}