Currently there are two overloads of the Expression.In method:
Code:
public static AbstractCriterion In( string propertyName, object[ ] values )
public static AbstractCriterion In( string propertyName, ICollection values )
However, since now generic collections are widely used, these two overload are not very convenient for creating InExpression using generic collections.
I think a overload to accept IEnumerable could be helpful. Thus I wrote two:
Code:
/// <summary>
/// Apply an "in" constraint to the named property
/// </summary>
/// <param name="propertyName">The name of the Property in the class.</param>
/// <param name="values">An IEnumerable of values.</param>
/// <returns>An <see cref="InExpression" />.</returns>
public static AbstractCriterion In(string propertyName, IEnumerable values)
{
IList l = new ArrayList();
foreach (object o in values) {
l.Add(o);
}
return In(propertyName, l);
}
This one is the most simple implementation. However it has two problems:
first, its signature could be confusing with the In( string propertyName, ICollection values ). since ICollection also inherits IEnumerable;
second, it relies on the performance of the ArrayList.Add method. For big IEumerable it could introduce performance issue.
The other implementation I wrote is as the following:
Code:
/// <summary>
/// Apply an "in" constraint to the named property
/// </summary>
/// <param name="propertyName">The name of the Property in the class.</param>
/// <param name="values">An IEnumerable of values.</param>
/// <param name="length">the number of the items in the IEnumerable that should be included in the expression.
/// It should always be larger than or equal to the number of the items of the IEnumerable
/// </param>
/// <returns>An <see cref="InExpression" />.</returns>
/// <exception cref="ArgumentOutOfRangeException">thrown when length is less than zero or is larger than the number of items in the IEnumerable </exception>
public static AbstractCriterion In(string propertyName, IEnumerable values, int length)
{
object[] ary = new object[length];
if (length > 0)
{
int i = 0;
foreach (object o in values)
{
ary[i] = o;
i++;
if (i >= length) break;
}
if (i <= length)
throw new ArgumentOutOfRangeException(
"length should be smaller than or equal to the number of items in the IEnumerable");
}
else
throw new ArgumentOutOfRangeException(
"length should be no less than 0");
return In(propertyName, ary);
}
This implementation has a different signature that won't messed with the other two existing one. It introduced a new parameter : length, which indicates the number of the items in the IEnumerable that need to be included in the in expression. This implementation also eliminate the dependency on ArrayList. However, it also has two problems:
first, the signature is two different from the existing ones, user needs to learn the usage of the new parameter.
second, the implementation is more complex and thus more subject to errors.
I listed both of the two implementations here because neither of them are perfect. But I do think that if the Expression.In can accept a IEnumerable rather than ICollection, it can be beneficial.
Thanks,