I have the following code:

static void foo<T>(this List<T> list, T t)
        {
            ...
        }

So in order to call the extension method I'll have to do this:

myList.foo<myType>(myVar);

Is it possible to change my code so that I can call my method like this:

myList.foo(myVar);

For, example the Remove function in List is called without specifying the type (myList.Remove(myVar) and not myList.Remove<myType>(myVar)).

Dani AI

Generated

A quick summary that ties together the replies from , and and explains why the compiler behaved the way it did.

Extension methods are regular static methods, so any type parameter symbol (like T) used inside the method must be declared on the method (or on the declaring type). Because extension methods must live in a static class (static classes cannot have type parameters), an extension that is generic has to declare its own <T> on the method. That is why removing the <T> from the method declaration produced a compile error, as saw.

Calling-site syntax is different: the compiler performs type inference for generic methods. The receiver (the this parameter of the extension) counts as an argument for inference, so the compiler can usually infer the method type argument from the list variable itself and/or other parameters. That is why an explicitly generic call is often unnecessary. This is also why Remove on List<T> never needs <> at the call site: Remove is an instance method declared on the generic type List<T> (the type parameter is on the type, not on the method).

Example (different from the thread examples) showing a generic extension where the type parameters are inferred from the receiver:

public static class DictionaryExtensions
{
    public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key)
    {
        return dict.TryGetValue(key, out TValue v) ? v : default(TValue);
    }
}

var map = new Dictionary<int, string>();
var s = map.GetValueOrDefault(42); // compiler infers TKey=int, TValue=string

If inference fails (ambiguous overloads, insufficient information, or multiple unrelated type parameters), the type arguments can be supplied explicitly. See the C# docs on extension methods and for the formal rules and edge cases.

Recommended Answers

All 9 Replies

Yes you can remove the <T> from the name of the function, like so:

static void foo(this List<T> list, T t)
      {
      ...
      }

Yes you can remove the <T> from the name of the function, like so:

static void foo(this List<T> list, T t)
      {
      ...
      }

Well, yes that's the first thing I tried doing, but:
The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)

No, since List<T> is technically not a type until you've given it one. So an extension method for a generic has to have a type so it 'knows' which type it is extending.

No, since List<T> is technically not a type until you've given it one. So an extension method for a generic has to have a type so it 'knows' which type it is extending.

Well isn't the type of List<T> determined during its initialization and not when one of its generic methods is called? If so, can't the method evaluate the list's type at runtime? I mean that's the whole point of generics, isn't it?

No, it's determined at compile time. The compiler generates a new type based on the generic version of List<T> given the type specified.

It's possible to do this at runtime (reflection), but still the extension method would need to know what type it is extending, thus you need to give it the T parameter.

Well, what do you mean the extension method doesn't know what type it's extending? Can't the compiler generate the new type based on the list it's extending and whose type it knows?

List<string> myList = new List<string>();

static void foo(this List<T> list, T t)
{
    ...
}

static void main()
{
    myList.foo();
}

Can't the compiler simply determine that myList contains elements of type string and therefore evaluate T as a string?

What about the Remove() method. How come it doesn't ask for a type?

You need to remember that at its heart, C# is a statically typed language. Generics came about in 2.0, and extension methods in 3.0. It isn't until 4.0 that we get the dynamic keyword.

While it would be possible for them to reflect over the class at runtime, you'd lose a lot of the static typing done. Also you'd lose the ability of the compiler to determine if a method is valid for a specific type. Method calls would have to reflect over the extension code each time to determine if there is an extension method to use, or if it should use the normal method based on parameters to the method call.

This would slow everything down, and no one wants slow.

I didn't manage to understand much, but it turns out that the following code is valid for some reason:

List<string> myList = new List<string>();
     
    static void foo<T>(this List<T> list)
    {
        ...
    }
     
    static void main()
    {
        myList.foo();
    }

I don't know why that's so, but it solves my problem.

Odd. The compiler must be doing more work than I thought it was :) Now I have to wonder what the point of method<T>(this T ...) is for. Time to start reading, I guess :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.