Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it impossible to declare extension methods in a generic static class?

Tags:

I'd like to create a lot of extension methods for some generic class, e.g. for

public class SimpleLinkedList<T> where T:IComparable

And I've started creating methods like this:

public static class LinkedListExtensions
{
    public static T[] ToArray<T>(this SimpleLinkedList<T> simpleLinkedList) where T:IComparable
    {
       //// code
    }
}

But when I tried to make LinkedListExtensions class generic like this:

public static class LinkedListExtensions<T> where T:IComparable
{
    public static T[] ToArray(this SimpleLinkedList<T> simpleLinkedList)
    {
         ////code
    }
}

I get "Extension methods can only be declared in non-generic, non-nested static class".

And I'm trying to guess where this restriction came from and have no ideas.

EDIT: Still don't have clear vision of the problem. It seems like this was just not implemented for some reason.

like image 210
Hun1Ahpu Avatar asked Apr 11 '10 18:04

Hun1Ahpu


People also ask

Can we define extension methods for static class?

Extension methods are defined as static methods but are called by using instance method syntax. Their first parameter specifies which type the method operates on. The parameter is preceded by the this modifier.

Can extension methods extend non static classes?

It is compulsion that the Extension method must be in a Static class only so that only one Instance is created. For example, if you place the following in ASP.Net page it will not work. Though error will not come, but you will not see the method available. The above will not work.

Are extension methods always static?

An extension method must be a static method. An extension method must be inside a static class -- the class can have any name. The parameter in an extension method should always have the "this" keyword preceding the type on which the method needs to be called.

Can a static class be generic?

A static generic class is exactly as useful as any given static class. The difference is that you don't have to use copy-and-paste to create a version of the static class for each type you want it to work on. You make the class generic, and you can "generate" one version for each set of type parameters.


2 Answers

Generally speaking, since you do not specify the class when you use an extension method, the compiler would have no way to know which is the class where the extension method is defined:

static class GenStatic<T>
{
  static void ExtMeth(this Class c) {/*...*/}
}

Class c = new Class();
c.ExtMeth(); // Equivalent to GenStatic<T>.ExtMeth(c); what is T?

Since extension methods themselves can be generic, this is no real problem at all:

static class NonGenStatic
{
  static void GenExtMeth<T>(this Class c) {/*...*/}
}

Class c = newClass();
c.ExtMeth<Class2>(); // Equivalent to NonGenStatic.ExtMeth<Class2>(c); OK

You can easily rewrite your example so that the static class is not generic, but the generic methods are. In fact, this is how .NET classes such as Enumerable are written.

  public static class LinkedListExtensions
  {
    public static T[] ToArray<T>(this SimpleLinkedList<T> where T:IComparable simpleLinkedList)
    {
      // code
    }
  }
like image 57
Gorpik Avatar answered Sep 27 '22 20:09

Gorpik


The problem is how does the compiler do the extension resolution?

Say you define both the methods you describe:

public static class LinkedListExtensions {
    public static T[] ToArray<T>(this SimpleLinkedList<T> simpleLinkedList) where T:IComparable {
        //// code
    }
}
public static class LinkedListExtensions<T> where T:IComparable {
    public static T[] ToArray(this SimpleLinkedList<T> simpleLinkedList) {
        ////code
    }
}

Which method is used in the following case?

SimpleLinkedList<int> data = new SimpleLinkedList<int>();
int[] dataArray = data.ToArray();

My guess is that the language designers decided to restrict extension methods to the non-generic types to avoid this scenario.

like image 37
Cameron MacFarland Avatar answered Sep 27 '22 19:09

Cameron MacFarland