Erweiterungsmethoden müssen in einer nicht generischen statischen Klasse definiert werden

213

Ich erhalte den Fehler:

Erweiterungsmethoden müssen in einer nicht generischen statischen Klasse definiert werden

An der Leitung:

public class LinqHelper

Hier ist die Hilfsklasse, die auf Mark Gavells Code basiert. Ich bin wirklich verwirrt darüber, was dieser Fehler bedeutet, da ich sicher bin, dass er gut funktioniert hat, als ich ihn am Freitag verlassen habe!

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
quelle

Antworten:

309

Veränderung

public class LinqHelper

zu

public static class LinqHelper

Folgende Punkte müssen beim Erstellen einer Erweiterungsmethode berücksichtigt werden:

  1. Die Klasse , die eine Verlängerung Methode definiert sein muss non-generic, staticundnon-nested
  2. Jede Erweiterungsmethode muss eine staticMethode sein
  3. Der erste Parameter der Erweiterungsmethode sollte das thisSchlüsselwort verwenden.
verschlüsselt
quelle
Wenn Sie die Klasse in App_Code platziert haben, muss das Schlüsselwort static in der Klassendefinition enthalten sein. Wenn Sie sie jedoch in einem anderen Ordner ablegen, ist es in Ordnung, sie als normale Klasse zu verwenden.
DT
1
In einem Fall hatte ich verwendet, public static class IQueryable<T> where T : MyBaseClasswas auch diesen Fehler erzeugt. Die where T : MyBaseClassPhrase gehört zu den einzelnen Methoden ohne <T>zur statischen Klasse.
Bron Davies
1
Aber was ist, wenn die Klasse Teilweise ist? Diese Lösung hat bei mir nicht funktioniert.
Fandango68
1
Danke Kumpel, ich habe den "this" -Parameter erwischt!
Roberto Gata
1
Beachten Sie, dass Sie diesen Compiler möglicherweise erhalten, wenn Sie Ihre Klasse versehentlich in eine Erweiterungsmethode konvertiert haben (je nach Compiler). Siehe diese Antwort in Bezug auf statische Methoden und diese Antwort in Bezug auf thisMethodenargumente.
Maarten Bodewes
25

Wenn Sie keine statischen Funktionen haben möchten, entfernen Sie einfach das Schlüsselwort "this" in den Argumenten.

Rohan Bhosale
quelle
6
Ich kratzte mir eine Weile am Kopf, um herauszufinden, warum Visual Studio dachte, ich würde versuchen, eine meiner Klassen zu einer Erweiterungsmethode zu machen. Es stellte sich heraus, dass ich ein thisSchlüsselwort in einer meiner Methodensignaturen vergraben hatte. Durch Entfernen wurde der Fehler behoben.
Fütemire
20

Schlüsselwort staticzur Klassendeklaration hinzufügen:

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

Versuchen Sie es zu ändern

public class LinqHelper

zu

 public static class LinqHelper
Nathan
quelle
15

Ändern Sie es in

public static class LinqHelper
Rik
quelle
15

Ein Workaround für Leute, die einen Fehler wie Nathan haben:

Der On-the-Fly-Compiler scheint ein Problem mit diesem Fehler der Erweiterungsmethode zu haben ... das Hinzufügen statichat mir auch nicht geholfen.

Ich würde gerne wissen, was den Fehler verursacht.

Aber die Work-around ist eine neue Erweiterung Klasse zu schreiben (nicht verschachtelt) sogar in derselben Datei und neu zu bauen.

Es wurde festgestellt, dass dieser Thread genügend Ansichten erhält, sodass es sich lohnt, die (begrenzte) Lösung weiterzugeben, die ich gefunden habe. Die meisten Leute haben wahrscheinlich versucht, "statisch" hinzuzufügen, bevor sie nach einer Lösung gesucht haben! und ich habe diese Problemumgehung nirgendwo anders gesehen.

Stephan Luis
quelle
Ich hatte das gleiche Problem. Ich habe gerade festgestellt, dass ich eine statische Funktion innerhalb der Klasse hinzugefügt und vergessen habe, sie zu kommentieren. Das machte meine Klasse statisch und gab daher diesen Fehler. Überprüfen Sie, ob Ihre Klasse statische Objekte enthält.
Mahesh
1

Die Erweiterungsmethode sollte sich in einer statischen Klasse befinden. Fügen Sie daher Ihre Erweiterungsmethode in eine statische Klasse ein.

so sollte es zum Beispiel so sein

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
quelle
Wie unterscheidet sich das von den Antworten vor Jahren?
Maarten Bodewes
1

Versuchen Sie, es in eine statische Klasse und zurück zu ändern. Das könnte dazu führen, dass sich Visual Studio beschwert, wenn es falsch positiv ist.

visc
quelle
0

Ich bin auf ein ähnliches Problem gestoßen. Ich habe einen 'foo'-Ordner erstellt und eine "Klasse" in foo erstellt. Dann erhalte ich den oben genannten Fehler. Eine Lösung besteht darin, der Klasse "statisch" hinzuzufügen, wie dies zuvor erwähnt wurde. Dies ist die "öffentliche statische Klasse LinqHelper".

Ich gehe davon aus, dass beim Erstellen einer Klasse im Ordner foo diese als Erweiterungsklasse betrachtet wird. Daher gilt für sie unter anderem die folgende Regel:

1) Jede Erweiterungsmethode muss eine statische Methode sein

Umgehung Wenn Sie keine statische Aufladung wünschen. Meine Problemumgehung bestand darin, eine Klasse direkt unter dem Namespace zu erstellen und sie dann in den Ordner "foo" zu ziehen.

Cashmoney007
quelle