Les méthodes d'extension doivent être définies dans une classe statique non générique

214

Je reçois l'erreur:

Les méthodes d'extension doivent être définies dans une classe statique non générique

Sur la ligne:

public class LinqHelper

Voici la classe d'assistance, basée sur le code Mark Gavells. Je suis vraiment confus quant à ce que signifie cette erreur car je suis sûr qu'elle fonctionnait bien quand je l'ai quittée vendredi!

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
la source

Réponses:

309

changement

public class LinqHelper

à

public static class LinqHelper

Les points suivants doivent être pris en compte lors de la création d'une méthode d'extension:

  1. La classe qui définit une méthode d'extension doit être non-generic,static etnon-nested
  2. Chaque méthode d'extension doit être une staticméthode
  3. Le premier paramètre de la méthode d'extension doit utiliser le thismot - clé.
crypté
la source
Si vous avez placé la classe dans App_Code, il est lié au mot clé statique dans la définition de classe, mais si vous le placez dans un autre dossier, il est préférable de l'utiliser comme classe normale.
DT
1
Dans un cas, j'avais utilisé public static class IQueryable<T> where T : MyBaseClassce qui génère également cette erreur. La where T : MyBaseClassphrase appartient aux méthodes individuelles sans <T>à la classe statique.
Bron Davies
1
Mais que se passe-t-il si la classe est partielle? Cette solution n'a pas fonctionné pour moi.
Fandango68
1
Merci mon pote, je suis tombé sur le paramètre "this"!
Roberto Gata
1
Attention, vous pouvez obtenir ce compilateur si vous avez involontairement converti votre classe en une méthode d'extension (selon le compilateur). Voir cette réponse en ce qui concerne les méthodes statiques et cette réponse en ce qui concerne les thisarguments de méthode.
Maarten Bodewes
27

si vous n'avez pas l'intention d'avoir des fonctions statiques, supprimez simplement le mot-clé "this" dans les arguments.

Rohan Bhosale
la source
7
Je me grattais la tête pendant un certain temps en essayant de comprendre pourquoi Visual Studio pensait que j'essayais de faire de l'une de mes classes une méthode d'extension. Il s'avère que j'avais un thismot - clé enfoui dans ma signature de méthode. Le supprimer a effacé l'erreur.
Fütemire
20

Ajouter un mot clé staticà la déclaration de classe:

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

Essayez de changer

public class LinqHelper

à

 public static class LinqHelper
Nathan
la source
15

Changez-le en

public static class LinqHelper
Rik
la source
15

Une solution de contournement pour les personnes qui connaissent un bug comme Nathan:

Le compilateur à la volée semble avoir un problème avec cette erreur de méthode d'extension ... l'ajout staticne m'a pas aidé non plus.

Je voudrais savoir ce qui cause le bogue?

Mais la solution consiste à écrire une nouvelle classe d'extension (non imbriquée) même dans le même fichier et à reconstruire.

J'ai pensé que ce fil obtenait suffisamment de vues qu'il valait la peine de transmettre la solution (limitée) que j'ai trouvée. La plupart des gens ont probablement essayé d'ajouter «statique» avant de rechercher une solution sur Google! et je n'ai vu cette solution de contournement nulle part ailleurs.

Stephan Luis
la source
J'ai eu le même problème. Je viens de réaliser que j'ai ajouté une fonction statique dans la classe et j'ai oublié de la commenter. Cela a donc rendu ma classe statique et a donc donné cette erreur. Vérifiez s'il y a des objets statiques dans votre classe.
Mahesh
1

La méthode d'extension doit se trouver dans une classe statique. Veuillez donc ajouter votre méthode d'extension dans une classe statique.

donc, par exemple, il devrait être comme ça

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
la source
En quoi est-ce différent des réponses données des années auparavant?
Maarten Bodewes
1

Essayez de le changer en classe statique et inversement. Cela pourrait résoudre les plaintes de Visual Studio lorsqu'il s'agit d'un faux positif.

visc
la source
0

J'ai rencontré un problème similaire, j'ai créé un dossier 'foo' et créé une "classe" à l'intérieur de foo, puis j'ai l'erreur susmentionnée. Un correctif consiste à ajouter "statique" comme mentionné précédemment à la classe qui sera "classe statique publique LinqHelper".

Mon hypothèse est que lorsque vous créez une classe dans le dossier foo, elle la considère comme une classe d'extension, d'où la règle, entre autres, qui lui est applicable:

1) Chaque méthode d'extension doit être une méthode statique

SOLUTION Si vous ne voulez pas d'électricité statique. Ma solution de contournement consistait à créer une classe directement sous l'espace de noms, puis à la faire glisser vers le dossier "foo".

Cashmoney007
la source