Metody rozszerzeń muszą być zdefiniowane w nieogólnej klasie statycznej

213

Pojawia się błąd:

Metody rozszerzeń muszą być zdefiniowane w nieogólnej klasie statycznej

Na linii:

public class LinqHelper

Oto klasa pomocnicza, oparta na kodzie Mark Gavells. Jestem naprawdę zdezorientowany, co oznacza ten błąd, ponieważ jestem pewien, że działał dobrze, kiedy go zostawiłem w piątek!

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
źródło

Odpowiedzi:

309

zmiana

public class LinqHelper

do

public static class LinqHelper

Podczas tworzenia metody rozszerzenia należy wziąć pod uwagę następujące punkty:

  1. Klasa, która definiuje metodę rozszerzenia, musi być non-generic, staticinon-nested
  2. Każda metoda rozszerzenia musi być staticmetodą
  3. Pierwszy parametr metody rozszerzenia powinien używać thissłowa kluczowego.
zaszyfrowane
źródło
Jeśli umieściłeś klasę w App_Code, to musi ona zawierać słowo kluczowe static w definicji klasy, ale jeśli umieścisz ją w innym folderze, możesz używać jej jako normalnej klasy.
DT
1
W jednym przypadku użyłem, public static class IQueryable<T> where T : MyBaseClassco również generuje ten błąd. where T : MyBaseClassWyrażenie należy na poszczególnych metod bez <T>od klasy statycznej.
Bron Davies
1
Ale co jeśli klasa jest częściowa? To rozwiązanie nie działało dla mnie.
Fandango68
1
Dzięki kolego, złapałem się na parametrze „ten”!
Roberto Gata,
1
Uwaga, możesz uzyskać ten kompilator, jeśli przypadkowo przekonwertujesz klasę na metodę rozszerzenia (zgodnie z kompilatorem). Zobacz tę odpowiedź w odniesieniu do metod statycznych i tę odpowiedź w odniesieniu do thisargumentów metody.
Maarten Bodewes
26

jeśli nie masz funkcji statycznych, po prostu pozbądź się słowa kluczowego „this” w argumentach.

Rohan Bhosale
źródło
6
Drapałem się po głowie, próbując dowiedzieć się, dlaczego Visual Studio myślało, że próbuję uczynić jedną z moich klas metodą rozszerzającą. Okazuje się, że mam thissłowo kluczowe zakopane w sygnaturach mojej metody. Usunięcie go usunęło błąd.
Fütemire,
20

Dodaj słowo kluczowe staticdo deklaracji klasy:

// this is a non-generic static class
public static class LinqHelper
{
}
abatishchev
źródło
16

Spróbuj zmienić

public class LinqHelper

do

 public static class LinqHelper
Nathan
źródło
15

Zmień to na

public static class LinqHelper
Rik
źródło
15

Obejście problemu dla osób, które mają taki błąd, jak Nathan:

Wydaje się, że kompilator w locie ma problem z tym błędem metody rozszerzenia ... dodanie staticteż mi nie pomogło.

Chciałbym wiedzieć, co powoduje błąd?

Ale obejściem tego jest napisanie nowej klasy Extension (nie zagnieżdżonej) nawet w tym samym pliku i przebudowanie.

Stwierdziłem, że ten wątek ma wystarczająco dużo widoków, że warto przekazać (ograniczone) rozwiązanie, które znalazłem. Większość osób prawdopodobnie próbowało dodać „statyczny” przed wyszukaniem rozwiązania w Google! i nigdzie indziej nie widziałem tego obejścia.

Stephan Luis
źródło
Miałem ten sam problem. Właśnie zdałem sobie sprawę, że dodałem funkcję statyczną w klasie i zapomniałem ją skomentować. To sprawiło, że moja klasa stała się statyczna, i dlatego dawałem ten błąd. Sprawdź, czy w twojej klasie są jakieś obiekty statyczne.
Mahesh,
1

Metoda rozszerzenia powinna znajdować się w klasie statycznej. Więc dodaj swoją metodę rozszerzenia do klasy statycznej.

więc na przykład tak powinno być

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
źródło
Czym różni się to od odpowiedzi udzielonych przed laty?
Maarten Bodewes
1

Spróbuj zmienić go na klasę statyczną i odwrotnie. To może rozwiązać problem wizualnego studia narzekającego, gdy jest to fałszywie pozytywne.

lepkość
źródło
0

Napotkałem podobny problem, utworzyłem folder „foo” i utworzyłem „klasę” wewnątrz foo, a następnie pojawia się wyżej wymieniony błąd. Jedną z poprawek jest dodanie „static”, jak wspomniano wcześniej, do klasy, która będzie „publiczną klasą statyczną LinqHelper”.

Zakładam, że kiedy tworzysz klasę w folderze foo, traktuje ją jako klasę rozszerzenia, dlatego stosuje się do niej następującą zasadę między innymi:

1) Każda metoda rozszerzenia musi być metodą statyczną

Obejście problemu Jeśli nie chcesz statycznego. Moim obejściem było utworzenie klasy bezpośrednio pod przestrzenią nazw, a następnie przeciągnięcie jej do folderu „foo”.

Cashmoney007
źródło