12

So, I ran across an answer by Servy ( https://stackoverflow.com/a/15098242/496680 ) and some of his code does this:

public static int BinarySearch<TSource, TKey>(...)

for an extension method, but he calls it like this:

arr.BinarySearch(...)

I asked around and somebody metioned that its an implied generic type parameter. I googled them but found no information on them. I understand how generics work but I'm failing to understand how/when to use these.

  1. Why does servy use them in his extention method?
  2. Is there a more official name for these that I can search for?
Community
  • 1
  • 1
Steve's a D
  • 3,801
  • 10
  • 39
  • 60
  • 2
    I can answer #1 simply enough. It allows the method to work with any type of collection, rather than only working for strings or ints or Foos or whatever. It also allows you to compare against any type of value, let it be an int or a string or a Bar or [...]. In your specific case you just needed to select an `int` from an array of some type (that I didn't even know the name of mind you). Using generics it will work not only for your one case, but any similar case that has the same problem but with different types. This will be more helpful for future visitors finding your question. – Servy Feb 26 '13 at 21:43
  • @Servy thanks! For future readers I also found this post: http://stackoverflow.com/questions/4885027/how-does-generic-type-inference-work-in-c – Steve's a D Feb 26 '13 at 21:46

3 Answers3

11

Well, you left out the most important part that makes it all work. The type parameters can be inferred by the actual object parameters passed in.

For instance:

static class Extensions {
  internal static IEnumerable<U> Test<T, U>(
                                   this IEnumerable<T> items,
                                   Func<T, U> converter) {
    foreach (T item in items) {
      yield return converter(item);
    }
  }
}

This extension method works on any IEnumerable class and will convert each item in the enumeration to another type based on the converter you provided. This is standard generics.

Now, there are many ways to call this method:

IEnumerable<int> values = Enumerable.Range<int>(1, 10);
Func<int, string> converter = i => i.ToString("0.00");

// Variation 1, explicit calling
IEnumerable<string> results1 = Extensions.Test<int, string>(values, converter);

// Variation 2, explicit calling with type inference
IEnumerable<string> results2 = Extensions.Test(values, converter);

// Variation 3, extension method calling, still providing explicit types
IEnumerable<string> results3 = values.Test<int, string>(converter);

// Variation 4, extension method with type inference
IEnumerable<string> results4 = values.Test(converter);

All four variations call the same method and return the same result. Type inference works by looking at the parameters passed and automatically inferring their types based on what's being provided. In our examples above, it's able to determine that type T is of type int because we passed in an IEnumerable<int> into the parameter for IEnumerable<T>. It is also able to infer that type U is of type string because we passed in a Func matching the initial type of T with int and returning a string. So the Func<T, U> is filled in with our converter function of Func<int, string>.

From the inference above, it's a standard generic method at that point. Type inference and extension methods are nothing more than convenience/syntactic sugar. In fact, if you decompile the output you can see that extension methods are replaced with static calls and are usually defined with the type parameters explicitly filled out. (This varies based on your decompiler and the set options).

Joshua
  • 8,112
  • 3
  • 35
  • 40
6
  1. He uses a generic method in this case because it allows his method to work with any type contained within a Collection<T>. The generic method makes this very flexible, and usable for any type. He uses the type inferrence when calling the method because it simplifies the code at the call site.

  2. The automatic handling is called Type Inferrence, and is covered, in detail, in the C# Language Specification, section 7.5.2: Type Inferrence. If you want to understand it in detail, I would recommend downloading the C# language specification.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
2

The term I usually hear is 'type inference'.

Brian Ball
  • 12,268
  • 3
  • 40
  • 51
  • Yes, it's called "type inference". There's a completely basic example at [Generic Methods (C# Programming Guide)](http://msdn.microsoft.com/en-us/library/twcad0zb.aspx) where it says: _You can also omit the type argument and the compiler will **infer** it. The following call to Swap is equivalent to the previous call: [...] The same rules for type inference apply to static methods and instance methods. The compiler can infer the type parameters based on the method arguments you pass in; it cannot infer the type parameters only from a constraint or return value. [...]_ – Jeppe Stig Nielsen Feb 26 '13 at 21:47