1

The Setup

I've got a method called WhereIn() that accepts a params object[] values:

public bool WhereIn(params object[] values)

The Problem

Unfortunately is it's really easy to make the mistake of calling WhereIn(values.Select(v => v.Id)).

This results a Linq expression being passed in, rather that the values getting enumerated to an array. How do I overload my method to accept the linq expression?

My Best Guess

My current best guess is to make an IEnumerable overload, and then have to check for it being a string, and then stuffing the string into an object array to call the other overload:

public bool WhereIn<T>(IEnumerable<T> values){
    if(values.GetType().Name == "String"){
        return WhereIn(new object[]{values});
    } else {
        // Do Stuff
    }
}

I'm not really happy about having to manually check for a string type, and I'm afraid I might miss some other class that implements IEnumerable, that should be wrapped in an object array .

Daryl
  • 18,592
  • 9
  • 78
  • 145
  • 3
    What are the semantics of `WhereIn`? – Jon Mar 22 '12 at 15:38
  • Related: http://stackoverflow.com/a/2128841/284240 – Tim Schmelter Mar 22 '12 at 15:43
  • @Jon It creates a Microsoft CRM QueryExpression, that gets used to generate a SQL statement on the server side. So I use it like this: crmdataContext.GetAllEntitiesWhereIn("contactid", guid1, guid2, guid3); – Daryl Mar 22 '12 at 16:08

4 Answers4

1

You might want to check out the System.Collections.Generic.Contains() method and save yourself un-needed headaches trying to "reinvent the wheel".

Alex
  • 23,004
  • 4
  • 39
  • 73
  • Except that I'm actually passing these parameters to a another method that I don't own that's part of Microsoft CRM, that then is used to build a QueryExpression and go query the database. Contains no work. :) – Daryl Mar 22 '12 at 16:02
  • A realistic example of what you want to achieve would be helpful. – Alex Mar 22 '12 at 16:20
1

If you have the following two signatures:

public bool WhereIn<T>(params T[] values);
public bool WhereIn<T>(IEnumerable<T> values);

... and you call it like this:

WhereIn("hi")

This will call the first method, passing it a single-element string[].

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • That actually might work. I was just figured there would be a way to specify a method that accepts linq expression like list.select(i => i.Id); – Daryl Mar 22 '12 at 16:18
  • @Daryl: `list.select(i => i.Id)` returns an `IEnumerable`, so this will work for that. – StriplingWarrior Mar 22 '12 at 16:20
  • @Daryl are you saying you want your method to take an `IEnumerable` and a linq expression? – Craig Mar 22 '12 at 17:03
  • @Craig Basically if you attempt to pass in list.select(i => i.id), it'll compile just fine, but bomb when it runs. So I need to enumerate the result to an array (call ToArray) then call the params object[] overload. I could do some weird type checks if the length of the params array is 1, but the developer would have no idea what I'm doing and why list.select(i => i.ID) magically works. – Daryl Mar 22 '12 at 17:11
  • @Daryl: Why would it "bomb when it runs?" I have tested this, and it works just fine if you pass in `list.Select(i => i.Id)`. – StriplingWarrior Mar 22 '12 at 17:26
  • @Daryl I think I was confused when you said "a method that accepts linq expression"...did you mean a method that accepts `IEnumerable`? If so then I think this answer is what you're after. I thought you had meant a predicate. – Craig Mar 22 '12 at 17:47
  • @StriplingWarrior It isn't this initial method that is bombing, it's the method that this method is calling. With your solution, I'm able to convert the IEnumerable to an object[], which then works fine. Without your solution, the base method WhereIn(params object[] values) calls will treat my ienumerable collection as a single object. – Daryl Mar 22 '12 at 18:28
0

What if you did something like this... Edit: I include a test method so you can try different select(a => a.Id) if you want

[TestMethod]
public void Test()
{
    var test = new[] {
        new { Id = 1, Name = "John" },
        new { Id = 2, Name = "George" },
    };

    if (WhereIn(test.Select(a => a.Name)))
    {

    }


}

//Works with value types, strings, and classes
public bool WhereIn<T>(IEnumerable<T> values)
{
    var objectArray = new object[values.Count()];

    for (int index = 0; index < values.Count(); index++)
    {
        objectArray[index] = values.ElementAt(index);
    }

    return WhereIn(objectArray);
}

// This was just for test purposes
public bool WhereIn(params object[] values)
{

     return true;
}

I have run this in Visual studio Test and seems to work.

Hope this helps.

bytebender
  • 7,371
  • 2
  • 31
  • 54
-1

I haven't tried it but could you not do

WhereIn(values.Select(v => v.Id).ToArray<Type_of_Value>())

where Type_of_Value is the type used in your values collection

Dave S
  • 775
  • 5
  • 7
  • idk, I didn't down vote you. the ToArray is ideally what I need to be calling, the only problem is you don't get a compiler error if you forget, but it will cause the program to error. So I'm trying to make more of a Pit of Success (http://blogs.msdn.com/b/brada/archive/2003/10/02/50420.aspx) – Daryl Mar 22 '12 at 17:03