扩展方法必须在非通用静态类中定义


213

我收到错误消息:

扩展方法必须在非通用静态类中定义

在线上:

public class LinqHelper

这是基于Mark Gavells代码的帮助程序类。我对这个错误的含义感到非常困惑,因为我确信当我在星期五离开它时,它可以正常工作!

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

Answers:


309

更改

public class LinqHelper

public static class LinqHelper

创建扩展方法时,需要考虑以下几点:

  1. 其限定一个扩展方法必须是类non-genericstaticnon-nested
  2. 每个扩展方法都必须是一个static方法
  3. 扩展方法的第一个参数应使用this关键字。

如果已将类放置在App_Code中,则它必然在类定义中具有static关键字,但是如果将其放置在任何其他文件夹中,则可以将其用作普通类。
DT

1
在一种情况下,我曾经使用过public static class IQueryable<T> where T : MyBaseClass它也会产生此错误。该where T : MyBaseClass短语属于单个方法,而不属于<T>静态类。
布朗·戴维斯

1
但是,如果班级是Partial呢?此解决方案对我不起作用。
Fandango68

1
谢谢伙伴,我陷入了“ this”参数!
罗伯托·加塔

1
请注意,如果不经意将类转换为扩展方法(根据编译器),则可能会使用此编译器。见这个答案有关于静态方法和这个答案与关于this方法的参数。
Maarten Bodewes,

26

如果您不打算使用静态函数,则只需删除参数中的“ this”关键字。


6
我摸索了一段时间,试图弄清楚为什么Visual Studio认为我试图将我的类之一作为扩展方法。原来我this在方法签名中埋有一个关键字。删除它可以清除错误。
富泰尔

20

static在类声明中添加关键字:

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

16

尝试改变

public class LinqHelper

 public static class LinqHelper


15

针对遇到Nathan之类错误的人的解决方法:

即时编译器似乎与此扩展方法错误有关……添加static也没有帮助。

我想知道导致此错误的原因?

但是解决方法是即使在同一文件中也要编写一个新的Extension类(不嵌套)并重新构建。

认为此线程获得了足够的视图,值得将我发现的(有限的)解决方案传递给我们。大多数人可能在Google搜索之前尝试添加“静态”!我在其他任何地方都没有看到此变通办法。


我遇到过同样的问题。我只是意识到我在类中添加了一个静态函数,却忘了对其进行注释。因此这使我的类成为静态类,因此出现此错误。检查您的类中是否有任何静态对象。
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

尝试将其更改为静态类并返回。这可能会解决Visual Studio误报时的抱怨。


0

我遇到了类似的问题,我在foo中创建了一个'foo'文件夹并创建了一个“ class”,然后出现上述错误。一种解决方法是将前面提到的“ static”添加到将成为“ public static class LinqHelper”的类中。

我的假设是,当您在foo文件夹中创建一个类时,会将其视为扩展类,因此以下规则尤其适用于它:

1)每个扩展方法都必须是静态方法

解决方法如果您不希望静态。我的解决方法是直接在名称空间下创建一个类,然后将其拖到“ foo”文件夹中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.