Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confused as to why this C# code compiles, while similar code does not

Let's take the following extension method:

static class Extensions {    public static bool In<T>(this T t, params T[] values)    {       return false;    } } 

I'm curious as to why this code compiles and runs:

var x = new Object(); IEnumerable<int> p = new List<int> { 1, 2, 3 }; var t2 = x.In(p); 

Within In, values is an Object[], as if the List<int> gets converted on the fly to an array. To me, it seems that params T[] does not match IEnumerable<int>, which is why I'm surprised this even runs.

Now this code:

var x = 5; IEnumerable<int> p = new List<int> { 1, 2, 3 }; var t2 = x.In(p); 

Does not run and generates the compiler error:

Error 2 Argument 2: cannot convert from 'System.Collections.Generic.IEnumerable' to 'int[]'

This is what I'd expect from the first one actually. Can someone explain what's going on here? Thanks!

like image 871
Mike Christensen Avatar asked Mar 04 '14 19:03

Mike Christensen


People also ask

Why it is called as C?

After language 'B', Dennis Ritchie came up with another language which was based upon 'B'. As in alphabets B is followed by C and hence he called this language as 'C'.

Why #is used in C?

In C/C++, the # sign marks preprocessor directives. If you're not familiar with the preprocessor, it works as part of the compilation process, handling includes, macros, and more. It actually adds code to the source file before the final compilation.

Is C being used?

Microsoft's Windows kernel is developed mostly in C, with some parts in assembly language. For decades, the world's most used operating system, with about 90 percent of the market share, has been powered by a kernel written in C.


1 Answers

Type inference converts your first call to

In<object>(x, p); 

The parameters of this closed generic method are object, params object[].
Therefore, passing p implicitly converts it to an object, which becomes the single item in the params array.

Your second call is inferred (because of the first parameter) to

In<int>(x, p); 

Here, the second parameter can either be an int[] (passing an array directly) or a series of ints (via params).
Since IEnumerable<int> is neither of those, you get an error.

like image 199
SLaks Avatar answered Sep 28 '22 01:09

SLaks