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;
    }
}

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.

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.


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
{
}

16

Spróbuj zmienić

public class LinqHelper

do

 public static class LinqHelper


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.


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;
        }

    }

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.


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”.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.