Os métodos de extensão devem ser definidos em uma classe estática não genérica

213

Estou recebendo o erro:

Os métodos de extensão devem ser definidos em uma classe estática não genérica

Na linha:

public class LinqHelper

Aqui está a classe auxiliar, baseada no código de Mark Gavells. Estou realmente confuso sobre o que esse erro significa, pois tenho certeza que estava funcionando bem quando o deixei na sexta-feira!

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
fonte

Respostas:

309

mudança

public class LinqHelper

para

public static class LinqHelper

Os pontos a seguir precisam ser considerados ao criar um método de extensão:

  1. A classe a qual define um método de extensão devem estar non-generic, staticenon-nested
  2. Todo método de extensão deve ser um staticmétodo
  3. O primeiro parâmetro do método de extensão deve usar a thispalavra - chave
criptografado
fonte
Se você colocou a classe no App_Code, ela deve ter a palavra-chave estática na definição da classe, mas se você a colocar em qualquer outra pasta, será bom usá-la como classe normal.
DT
1
Em um caso, eu tinha usado o public static class IQueryable<T> where T : MyBaseClassque também gera esse erro. A where T : MyBaseClassfrase pertence aos métodos individuais sem <T>na classe estática.
Bron Davies
1
Mas e se a classe for Parcial? Esta solução não funcionou para mim.
Fandango68
1
Obrigado amigo, fui pego no parâmetro "this"!
Roberto Gata
1
Lembre-se de que você poderá obter esse compilador se converter inadvertidamente sua classe em um método de extensão (de acordo com o compilador). Veja esta resposta com relação aos métodos estáticos e esta resposta com relação aos thisargumentos do método.
Maarten Bodewes
26

se você não pretende ter funções estáticas, livre-se da palavra-chave "this" nos argumentos.

Rohan Bhosale
fonte
6
Eu estava coçando a cabeça por um tempo tentando descobrir por que o Visual Studio pensava que eu estava tentando transformar uma de minhas aulas em um método de extensão. Acontece que eu tinha uma thispalavra - chave enterrada em minhas assinaturas de método. A remoção limpou o erro.
Fütemire
20

Adicione a palavra static- chave à declaração de classe:

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

Tente mudar

public class LinqHelper

para

 public static class LinqHelper
Nathan
fonte
15

Mude para

public static class LinqHelper
Rik
fonte
15

Uma solução alternativa para pessoas que estão enfrentando um erro como Nathan:

O compilador on-the-fly parece ter um problema com este erro do método de extensão ... a adição statictambém não me ajudou.

Gostaria de saber o que causa o erro?

Mas a solução alternativa é escrever uma nova classe de extensão (não aninhada), mesmo no mesmo arquivo e recriar.

Percebi que esse segmento está obtendo visualizações suficientes para que valha a pena passar (a solução limitada) que encontrei. A maioria das pessoas provavelmente tentou adicionar 'estático' antes do google para obter uma solução! e não vi essa solução alternativa em nenhum outro lugar.

Stephan Luis
fonte
Eu tive o mesmo problema. Acabei de perceber que adicionei uma função estática na classe e esqueci de comentar. Então isso tornou minha classe estática e, portanto, estava dando esse erro. Verifique se há algum objeto estático na sua classe.
Mahesh
1

O método de extensão deve estar dentro de uma classe estática. Portanto, adicione seu método de extensão dentro de uma classe estática.

por exemplo, deve ser assim

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
fonte
Como isso é diferente das respostas dadas anos antes?
Maarten Bodewes
1

Tente alterá-lo para classe estática e vice-versa. Isso pode resolver as reclamações do visual studio quando se trata de um falso positivo.

visc
fonte
0

Eu encontrei um problema semelhante, criei uma pasta 'foo' e criei uma "classe" dentro de foo. Em seguida, recebo o erro mencionado acima. Uma correção é adicionar "estático", como mencionado anteriormente à classe, que será "classe estática pública LinqHelper".

Minha suposição é que, quando você cria uma classe dentro da pasta foo, ela a considera uma classe de extensão, portanto, a seguinte regra se aplica a ela:

1) Todo método de extensão deve ser um método estático

SOLUÇÃO ALTERNATIVA Se você não quiser estática. Minha solução alternativa foi criar uma classe diretamente sob o espaço para nome e arraste-a para a pasta "foo".

Cashmoney007
fonte