繁体   English   中英

我可以在.NET 2.0或3.0中使用扩展方法和LINQ吗?

[英]Can I use extension methods and LINQ in .NET 2.0 or 3.0?

当我尝试使用.NET 2.0或3.0运行时添加扩展方法时,出现错误消息:

无法定义新的扩展方法,因为找不到编译器所需的类型'System.Runtime.CompilerServices.ExtensionAttribute'。 您是否缺少对System.Core.dll的引用?

但是,当我尝试将System.Core添加到项目中时,找不到它。 为了能够使用扩展方法并在项目中启用LINQ ,我需要做什么?

直到3.5才将扩展方法添加到.NET。 但是,这不是对CLR 的更改 ,而是对添加它们的编译器的更改 ,因此您仍然可以在2.0和3.0项目中使用它们! 唯一的要求是您必须具有可以创建3.5个项目的编译器才能执行此解决方法(Visual Studio 2008及更高版本)。

尝试使用扩展方法时遇到的错误会误导您,因为您实际上并不需要System.Core.dll来使用扩展方法。 当您使用扩展方法时,在后台,编译器将[Extension]属性添加到该函数。 如果您的编译器了解[Extension]属性的作用,那么您可以在自己的2.0和3.0项目中使用该属性。

只需将以下类添加到您的项目中,即可开始使用扩展方法:

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    public class ExtensionAttribute : Attribute
    {
    }
}

上面的代码块位于System.Core.Dll内 ,因此这就是为什么错误提示您需要包括DLL文件才能使用它们的原因。


现在,如果您需要LINQ功能,则需要做一些额外的工作。 您将需要自己重新实现扩展方法。 为了模仿完整的LINQ to SQL功能,代码可能会变得非常复杂。 但是,如果您仅使用LINQ to Objects,则大多数LINQ方法实现起来并不复杂。 这是我为入门而编写的项目中的一些LINQ to Objects替换功能。

public static class LinqReplacement
{
    public delegate TResult Func<T, TResult>(T arg);
    public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);

    public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
    {
        if (source == null)
            throw new ArgumentNullException("source");
        if (predicate == null)
            throw new ArgumentNullException("predicate");

        foreach (TSource item in source)
        {
            if (predicate(item) == true)
                return item;
        }

        throw new InvalidOperationException("No item satisfied the predicate or the source collection was empty.");
    }

    public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source)
    {
        if (source == null)
            throw new ArgumentNullException("source");

        foreach (TSource item in source)
        {
            return item;
        }

        return default(TSource);
    }

    public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source)
    {
        foreach (object item in source)
        {
            yield return (TResult)item;
        }
    }

    public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
    {
        if (source == null)
            throw new ArgumentNullException("source");
        if (selector == null)
            throw new ArgumentNullException("selector");

        foreach (TSource item in source)
        {
            foreach (TResult subItem in selector(item))
            {
                yield return subItem;
            }
        }
    }

    public static int Count<TSource>(this IEnumerable<TSource> source)
    {
        var asCollection = source as ICollection;
        if(asCollection != null)
        {
            return asCollection.Count;
        }

        int count = 0;
        foreach (TSource item in source)
        {
            checked //If we are counting a larger than int.MaxValue enumerable this will cause a OverflowException to happen when the counter wraps around.
            {
                count++;
            }
        }
        return count;
    }
}

可以在LinqBridge项目(感谢Allon Guralnek )中找到一个库,该库具有对LINQ完全重新实现的对象(已经添加了ExtensionAttribute )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM