1

I have a big collection of objects of different built-in types, e.g. int, bool[], double[] etc.

On object M I wanted to perform an operation MyMethod once with each element of the collection. However, I needed to perform different operation with arrays and different with single values.

Firstly, I tried:

public void MyMethod<T>(T value)

public void MyMethod<T>(T[] array)

but then, the first method was applied with every element of the collection, including arrays.

My next try was:

public void MyMethod<T>(T value) where T : struct

public void MyMethod<T>(T[] array)

And it had a following effect when I tried to call that method:

Error 8 The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'MyMethod(T)'

It seems like the compiler doesn't see the MyMethod(T[] array) method. Where am I wrong?

Finally, I provided an auxiliary method:

public void MyAux<T>(T value) {
    if (value.GetType().IsArray) {
        this.MyMethodForArray(value);
    }
    else {
        this.MyMethodForSingleValue(value);
    }

but then I got an error:

Error 8 The type arguments for method 'MyMethodForArray(T[])' cannot be inferred from the usage. Try specifying the type arguments explicitly.

How to manage this problem elegantly?

Denikin
  • 11
  • 1
  • I just tried replicating the same but the functions are being called correctly(i.e. Array Generic methods for arrays passed and regular version for non array arguments.) – Chandu Dec 16 '10 at 14:56
  • Your first approach should work fine – Saeed Amiri Dec 16 '10 at 14:59
  • try MyMethod(IEnumerable array) – Bonshington Dec 16 '10 at 14:59
  • I haven't informed you that I want the type T to be inferred from the call. – Denikin Dec 16 '10 at 16:22
  • I iterate through the collection handing its elements as object type instances and I pass them to the MyMethod calls. Maybe approaches like the 1st and the 2nd cannot be successful. – Denikin Dec 16 '10 at 16:28
  • See also [an I prevent a specific type using generic restrictions](http://stackoverflow.com/questions/3891157/an-i-prevent-a-specific-type-using-generic-restrictions) – Brian Dec 17 '10 at 14:20

3 Answers3

5

If it hurts when you do that, don't do that. You'll notice that the List data types in the framework have an Add and an AddRange method. A method that takes an item and a method that takes a collection of items are logically different enough that it makes sense to give them different names. Rather than banging your head against the type system, just change the name of one of them.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
4

Creating a simple program as below

class Program
{
    static void Main(string[] args)
    {
        Foo t = new Foo();
        // Line numbering for convenience
        t.MyMethod<bool>(true);                     // #1
        t.MyMethod<bool>(new bool[] { true });      // #2
        t.MyMethod<bool[]>(new bool[] { true });    // #3
    }
}

public class Foo
{
    public void MyMethod<T>(T value)
    {
        Console.WriteLine("Single element method called");
    }

    public void MyMethod<T>(T[] array)
    {
        Console.WriteLine("Array method called");
    }
}

the output will be:

Single element method called
Array method called
Single element method called

I suspect you called the method as in line #3 where you were planning to call it as in line #2. Notice that the difference is in the two additional square brackets.

Jeroen
  • 1,246
  • 11
  • 23
3

Only have one version of your function (the array version), but declare it with the params keyword like so:

public void MyMethod<T>(params T[] array)

Something else you might explore is using IEnumerable<T> rather than T[]

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • As I can understand the `OP` wants do different thing with array. by your approach what is difference with method call by input of array of size 1 and a method call with one simple input? – Saeed Amiri Dec 16 '10 at 15:02
  • @Saeed - I thought that at first, but the more I looked at the question the less obvious it seemed and the more it looked like he just wanted to provide an easier way to call his function with a sequence. – Joel Coehoorn Dec 16 '10 at 15:04
  • @Saeed, Joel's answer assumes the "something different" is iterating over the array. There would be no difference in processing the elements. If the "something different" is something *remarkably* different, then this answer obviously would not work. – Anthony Pegram Dec 16 '10 at 15:04