hardfork
hardfork

Reputation: 3271

How to overload a method to support a params array and IEnumerable but interpret an IEnumerable always as IEnumerable?

I wrote this overloaded method to allow the caller to pass whatever he/she wants (IEnumerable, List, HashSet, an array of Ts, but also multiple T values - comma separated):

public void Values<T>(IEnumerable<T> ts)
{
    Test(ts);
}

public void Values<T>(params T[] ts)
{
    Test(ts);
}

private void Test<T>(IEnumerable<T> ts)
{
    // I expect this method to receive an IEnumerable with at least 2
    // elements in it.
}

What I have not expected: The call Values(new List<string> {"a", "b"}) actually calls the 2nd method rather than the first one. I guess, that's because the params array is older than IEnumerable

The problem in this case: My second method calls another method with an array that contains the list. That's not what I intended.

If I'd remove the first method, I won't be able to pass a hashset. If I'd remove the second method, I won't be able to pass the values comma separated.

What is a proper way to solve this dilemma?

  1. If one value is passed and it implements IEnumerable, then I want to pass its values to the Test() method.
  2. If one value is passed and it does not implement IEnumerable, then I want to pass that value within an IEnumerable or array to the Test() method.
  3. If multiple values are passed, then I want to pass those values to the Test() method.

I experimented with generic constraints and ugly reflection code but haven't found any solution.

Upvotes: 2

Views: 730

Answers (1)

Alexander Petrov
Alexander Petrov

Reputation: 14251

Either add AsEnumerable(), or explicitly specify the type of generics. And you will get a call to the desired method overload.

var list = new List<int>();

Values(list); // params

Values(list.AsEnumerable()); // IEnumerable
Values<int>(list); // IEnumerable

Upvotes: 1

Related Questions