Metode ekstensi harus didefinisikan dalam kelas statis non-generik


214

Saya mendapatkan kesalahan:

Metode ekstensi harus didefinisikan dalam kelas statis non-generik

Di telepon:

public class LinqHelper

Ini adalah kelas pembantu, berdasarkan pada kode Mark Gavells. Saya benar-benar bingung apa artinya kesalahan ini karena saya yakin itu berfungsi dengan baik ketika saya meninggalkannya pada hari Jumat!

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

Jawaban:


309

perubahan

public class LinqHelper

untuk

public static class LinqHelper

Poin-poin berikut perlu dipertimbangkan saat membuat metode ekstensi:

  1. Kelas yang mendefinisikan metode ekstensi harus non-generic, staticdannon-nested
  2. Setiap metode ekstensi harus berupa staticmetode
  3. Parameter pertama dari metode ekstensi harus menggunakan thiskata kunci.

Jika Anda telah menempatkan kelas di App_Code maka itu pasti memiliki kata kunci statis dalam definisi kelas, tetapi jika Anda menempatkannya di folder lain maka tidak apa-apa untuk menggunakannya sebagai kelas normal.
DT

1
Dalam satu kasus, saya telah menggunakan public static class IQueryable<T> where T : MyBaseClassyang juga menghasilkan kesalahan ini. The where T : MyBaseClassfrase milik pada metode individu tanpa <T>di kelas statis.
Bron Davies

1
Tetapi bagaimana jika kelasnya Partial? Solusi ini tidak berhasil untuk saya.
Fandango68

1
Terima kasih sobat, saya terjebak pada parameter "ini"!
Roberto Gata

1
Berhati-hatilah bahwa Anda dapat memperoleh kompiler ini jika Anda secara tidak sengaja mengkonversi kelas Anda ke metode ekstensi (sesuai dengan kompiler). Lihat jawaban ini berkaitan dengan metode statis dan jawaban ini berkaitan dengan thisargumen metode.
Maarten Bodewes

27

jika Anda tidak berniat memiliki fungsi statis, singkirkan saja kata kunci "ini" dalam argumen.


7
Saya menggaruk-garuk kepala untuk sementara waktu mencoba mencari tahu mengapa Visual Studio berpikir saya mencoba membuat salah satu kelas saya metode ekstensi. Ternyata saya memiliki thiskata kunci yang terkubur di dalam tanda tangan metode saya. Menghapusnya menghapus kesalahan.
Fütemire

20

Tambahkan kata kunci staticke deklarasi kelas:

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

16

Coba ubah

public class LinqHelper

untuk

 public static class LinqHelper

15

Ubah ke

public static class LinqHelper

15

Solusi untuk orang-orang yang mengalami bug seperti Nathan:

Kompilator on-the-fly tampaknya memiliki masalah dengan kesalahan Metode Ekstensi ini ... menambahkan statictidak membantu saya juga.

Saya ingin tahu apa yang menyebabkan bug?

Tetapi yang perlu dilakukan adalah menulis kelas Extension baru (tidak bersarang) bahkan dalam file yang sama dan membangun kembali.

Berpikir bahwa utas ini mendapatkan pandangan yang cukup sehingga layak diteruskan (terbatas) solusi yang saya temukan. Kebanyakan orang mungkin mencoba menambahkan 'statis' sebelum mencari solusi! dan saya tidak melihat perbaikan di sekitar ini di tempat lain.


Saya memiliki masalah yang sama. Saya baru menyadari bahwa saya menambahkan fungsi statis di dalam kelas dan lupa berkomentar. Sehingga membuat kelas saya statis, dan karenanya memberikan kesalahan ini. Periksa apakah ada objek statis di kelas Anda.
Mahesh

1

Metode ekstensi harus di dalam kelas statis. Jadi tolong tambahkan metode ekstensi Anda di dalam kelas statis.

jadi misalnya harus seperti ini

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

    }

Bagaimana ini berbeda dari jawaban yang diberikan bertahun-tahun sebelumnya?
Maarten Bodewes

1

Coba ubah ke kelas statis dan kembali. Itu mungkin menyelesaikan pengaduan visual studio ketika itu positif palsu.


0

Saya mengalami masalah serupa, saya membuat folder 'foo' dan membuat "class" di dalam foo, lalu saya mendapatkan kesalahan yang disebutkan di atas. Salah satu perbaikannya adalah menambahkan "statis" seperti yang disebutkan sebelumnya ke kelas yang akan menjadi "kelas statis publik LinqHelper".

Asumsi saya adalah bahwa ketika Anda membuat kelas di dalam folder foo menganggapnya sebagai kelas ekstensi, maka aturan antara lain berikut berlaku untuk itu:

1) Setiap metode ekstensi harus berupa metode statis

WORKAROUND Jika Anda tidak ingin statis. Solusi saya adalah membuat kelas langsung di bawah namespace dan kemudian seret ke folder "foo".

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.