Методи розширення повинні бути визначені в негенеричному статичному класі


213

Я отримую помилку:

Методи розширення повинні бути визначені в негенеричному статичному класі

На лінії:

public class LinqHelper

Ось клас хелперів, заснований на коді Марка Гевеллса. Я дуже розгублений, що означає ця помилка, оскільки я впевнений, що вона працювала нормально, коли я залишила її в п’ятницю!

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

Відповіді:


309

змінити

public class LinqHelper

до

public static class LinqHelper

Наступні моменти потрібно враховувати при створенні методу розширення:

  1. Клас , який визначає метод розширення повинен бути non-generic, staticіnon-nested
  2. Кожен метод розширення повинен бути staticметодом
  3. Перший параметр методу розширення повинен використовувати thisключове слово.

Якщо ви розмістили клас у App_Code, то у нього обов'язково буде статичне ключове слово у визначенні класу, але якщо ви помістите його в будь-яку іншу папку, то його штраф буде використовувати його як звичайний клас.
DT

1
В одному випадку я використав, public static class IQueryable<T> where T : MyBaseClassякий також генерує цю помилку. where T : MyBaseClassФраза належить на окремих методів без <T>на статичному класі.
Брон Девіс

1
Але що робити, якщо клас частковий? Це рішення для мене не спрацювало.
Fandango68

1
Дякую приятелю, я потрапив на параметр "цей"!
Роберто Гата

1
Не забудьте отримати цей компілятор, якщо ви ненавмисно перетворили свій клас на метод розширення (відповідно до компілятора). Дивіться цю відповідь щодо статичних методів та цю відповідь щодо thisаргументів методу.
Maarten Bodewes

26

якщо ви не маєте наміру мати статичні функції, просто позбудьтесь цього ключового слова в аргументах.


6
Я деякий час чухав голову, намагаючись з'ясувати, чому Visual Studio думає, що я намагаюся зробити один із моїх занять методом розширення. Виявляється, у мене було підписане thisключове слово на моїх підписах методу. Видаливши її, очищена помилка.
Фютемір

20

Додати ключове слово staticдо декларації класу:

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



15

Робота навколо людей, які відчувають помилку, як Натан:

У компілятора на ходу, здається, є проблема з помилкою цього методу розширення ... додавання staticмені теж не допомогло.

Я хотів би знати, що викликає помилку?

Але вирішення проблеми полягає в тому, щоб написати новий клас розширення (не вкладений) навіть у той самий файл і відновити його.

Зрозуміло, що ця тема отримує достатньо переглядів, що варто передати (обмежене) рішення, яке я знайшов. Більшість людей, ймовірно, намагалися додати "статичний" перед google-ing для вирішення! і я ніде більше не бачив цього виправлення.


У мене було те саме питання. Я щойно зрозумів, що додав статичну функцію в межах класу і забув прокоментувати її. Тож це зробило мій клас статичним, а значить, і дала цю помилку. Перевірте, чи є у вашому класі статичні об’єкти.
Mahesh

1

Метод розширення повинен знаходитися всередині статичного класу. Тому, будь ласка, додайте свій метод розширення всередині статичного класу.

так, наприклад, воно повинно бути таким

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

    }

Чим це відрізняється від відповідей, наданих роками раніше?
Maarten Bodewes

1

Спробуйте змінити його на статичний клас і назад. Це може вирішити візуальну студію, яка скаржиться, коли це хибний позитив.


0

У мене виникли подібні проблеми, я створив папку 'foo' і створив "клас" усередині foo, тоді я отримую вищезгадану помилку. Одне виправлення полягає в тому, щоб додати "статичний", як згадувалося раніше, до класу, який буде "публічним статичним класом LinqHelper".

Моє припущення, що коли ви створюєте клас у папці foo, він розглядає його як клас розширення, отже, до нього застосовується таке, серед іншого, правило:

1) Кожен метод розширення повинен бути статичним методом

РОБОТИ Якщо ви не хочете статики. Моє вирішення полягало в тому, щоб створити клас безпосередньо під простором імен, а потім перетягнути його в папку "foo".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.