Los métodos de extensión deben definirse en una clase estática no genérica

214

Me sale el error:

Los métodos de extensión deben definirse en una clase estática no genérica

En la línea:

public class LinqHelper

Aquí está la clase auxiliar, basada en el código de Mark Gavells. ¡Estoy realmente confundido sobre lo que significa este error, ya que estoy seguro de que estaba funcionando bien cuando lo dejé el viernes!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Linq.Expressions;
using System.Reflection;

/// <summary>
/// Helper methods for link
/// </summary>
public class LinqHelper
{
    public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property)
    {
        return ApplyOrder<T>(source, property, "OrderBy");
    }
    public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property)
    {
        return ApplyOrder<T>(source, property, "OrderByDescending");
    }
    public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property)
    {
        return ApplyOrder<T>(source, property, "ThenBy");
    }
    public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property)
    {
        return ApplyOrder<T>(source, property, "ThenByDescending");
    }
    static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName)
    {
        string[] props = property.Split('.');
        Type type = typeof(T);
        ParameterExpression arg = Expression.Parameter(type, "x");
        Expression expr = arg;
        foreach (string prop in props)
        {
            // use reflection (not ComponentModel) to mirror LINQ
            PropertyInfo pi = type.GetProperty(prop);
            expr = Expression.Property(expr, pi);
            type = pi.PropertyType;
        }
        Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
        LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);

        object result = typeof(Queryable).GetMethods().Single(
                method => method.Name == methodName
                        && method.IsGenericMethodDefinition
                        && method.GetGenericArguments().Length == 2
                        && method.GetParameters().Length == 2)
                .MakeGenericMethod(typeof(T), type)
                .Invoke(null, new object[] { source, lambda });
        return (IOrderedQueryable<T>)result;
    }
}
Tom Gullen
fuente

Respuestas:

309

cambio

public class LinqHelper

a

public static class LinqHelper

Deben tenerse en cuenta los siguientes puntos al crear un método de extensión:

  1. La clase que define un método de extensión debe ser non-generic, staticynon-nested
  2. Cada método de extensión debe ser un staticmétodo
  3. El primer parámetro del método de extensión debe usar la thispalabra clave.
encriptado
fuente
Si ha colocado la clase en App_Code, es probable que tenga la palabra clave estática en la definición de clase, pero si la coloca en cualquier otra carpeta, entonces está bien usarla como clase normal.
DT
1
En un caso, había usado lo public static class IQueryable<T> where T : MyBaseClassque también genera este error. La where T : MyBaseClassfrase pertenece a los métodos individuales sin <T>la clase estática.
Bron Davies
1
Pero, ¿y si la clase es parcial? Esta solución no me funcionó.
Fandango68
1
Gracias amigo, quedé atrapado en el parámetro "esto"!
Roberto Gata
1
Tenga en cuenta que puede obtener este compilador si involuntariamente convirtió su clase a un método de extensión (según el compilador). Vea esta respuesta con respecto a los métodos estáticos y esta respuesta con respecto a los thisargumentos del método.
Maarten Bodewes
27

Si no tiene la intención de tener funciones estáticas, simplemente elimine la palabra clave "this" en los argumentos.

Rohan Bhosale
fuente
77
Me estaba rascando la cabeza por un tiempo tratando de entender por qué Visual Studio pensaba que estaba tratando de hacer de una de mis clases un método de extensión. Resulta que tenía una thispalabra clave enterrada en mis firmas de método. Al eliminarlo se borró el error.
Fütemire
20

Agregar palabra clave statica la declaración de clase:

// this is a non-generic static class
public static class LinqHelper
{
}
abatishchev
fuente
16

Intenta cambiar

public class LinqHelper

a

 public static class LinqHelper
Nathan
fuente
15

Cámbialo a

public static class LinqHelper
Rik
fuente
15

Una solución alternativa para las personas que están experimentando un error como Nathan:

El compilador sobre la marcha parece tener un problema con este error de Método de extensión ... agregar statictampoco me ayudó.

Me gustaría saber qué causa el error.

Pero la solución es escribir una nueva clase de Extensión (no anidada) incluso en el mismo archivo y volver a compilar.

Pensé que este hilo está obteniendo suficientes vistas que vale la pena transmitir (la solución limitada) que encontré. ¡La mayoría de la gente probablemente intentó agregar 'estática' antes de buscar una solución en Google! y no vi esta solución alternativa en ningún otro lado.

Stephan Luis
fuente
Tuve el mismo problema. Me acabo de dar cuenta de que agregué una función estática dentro de la clase y olvidé comentarla. Eso hizo que mi clase fuera estática y, por lo tanto, estaba dando este error. Compruebe si hay objetos estáticos en su clase.
Mahesh
1

El método de extensión debe estar dentro de una clase estática. Entonces, agregue su método de extensión dentro de una clase estática.

así, por ejemplo, debería ser así

public static class myclass
    {
        public static Byte[] ToByteArray(this Stream stream)
        {
            Int32 length = stream.Length > Int32.MaxValue ? Int32.MaxValue : Convert.ToInt32(stream.Length);
            Byte[] buffer = new Byte[length];
            stream.Read(buffer, 0, length);
            return buffer;
        }

    }
Debendra Dash
fuente
¿Cómo es esto diferente de las respuestas dadas años antes?
Maarten Bodewes
1

Intente cambiarlo a clase estática y viceversa. Eso podría resolver las quejas de Visual Studio cuando es un falso positivo.

visc
fuente
0

Encontré un problema similar, creé una carpeta 'foo' y creé una "clase" dentro de foo, luego recibí el error antes mencionado. Una solución es agregar "estática" como se mencionó anteriormente a la clase que será "clase estática pública LinqHelper".

Mi suposición es que cuando crea una clase dentro de la carpeta foo la considera como una clase de extensión, por lo tanto, se aplica la siguiente regla, entre otras:

1) Cada método de extensión debe ser un método estático

Propocionar comentarios Solución Si no desea estática. Mi solución era crear una clase directamente debajo del espacio de nombres y luego arrastrarla a la carpeta "foo".

Cashmoney007
fuente