views:

1138

answers:

4

Hi there,

I have a list which contains enums, its a standard Enum but has an attribute attached to it and an extension method which returns a CHAR of the enum (see below - GetCharValue), the extension works great.

Now I have (another extension method for 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;
    }

I basically need to say "Return" everything in query but only if v.Status is in buildingStatus... but remember buildingStatus is an ILIST of enums so I MUST call GetCharValue.

I had some help previously had i think the correct syntax is

   buildingStatus.Contains (v.Status)

but the problem is here that buildingStatus is a Ilist of Enums so i must call GetCharValue() on each Item in the Ilist before saying Contains..

I was thinking there was something special way of doing this with lambda using Contains like so - of course it doesn't work

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

Can anyone help?

+6  A: 

Use Any() instead of Contains:

buildingStatus.Any(item => item.GetCharValue() == v.Status)
Rex M
+1  A: 

The Linq extension method Any could work for you...

buildingStatus.Any(item => item.GetCharValue() == v.Status)
flq
+1  A: 

I'm not sure precisely what you're looking for, but this program:

    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);
    }

produces the expected output:

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


This program compares a string representation of the enum and produces the same output:

    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 ();
    }


I created this extension method to convert one IEnumerable to another, but I'm not sure how efficient it is; it may just create a list behind the scenes.

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

Then you can change the where clause to:

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

and skip creating the List<string> with ConvertAll () at the beginning.

XXXXX
Thanks larry that worked, here is what i did by refering to your code... But it would be nice if possible if i didn't have to create a new list????// Used ToList because its an ILIST and run my GetCharValue// this produces a "NEW" list with my char'svar statusStringList = building.ToList().ConvertAll<char>(st => st.GetCharValue()); var test = from v in qry where statusStringList.Contains(v.Status) select v;All works, as i say it would be nice not having to do a new list or using a lambda inside Contains but appears its NOT possible?
mark smith
I assume the status property is a string; you therefore have to convert the status enums to strings for each comparison. You might as well convert them once at the beginning and be done with it.
XXXXX
Note: It's very irritating to be downvoted with no commentary.
XXXXX
A: 

If I understand correctly, you need to convert the type (char value) that you store in Building list to the type (enum) that you store in buildingStatus list.

(For each status in the Building list//character value//, does the status exists in the buildingStatus list//enum value//)

public static IQueryable WithStatus(this IQueryable qry,
IList 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; }