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

标签 c# .net .net-2.0 extension-methods .net-3.0

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

Cannot define a new extension method because the compiler required type 'System.Runtime.CompilerServices.ExtensionAttribute' cannot be found. Are you missing a reference to System.Core.dll?

但是当我尝试将它添加到项目时,我无法在可用引用列表中找到 System.Core。我需要做什么才能使用扩展方法并反过来 LINQ在我的项目中?

最佳答案

直到 3.5 才将扩展方法添加到 .NET 中。然而,这不是对 CLR 的更改,而是 a change to the compiler添加了它们,因此您仍然可以在 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 中找到一个完全重新实现 LINQ to Objects 并添加了 ExtensionAttribute 的库。项目(感谢 Allon Guralnek )。

关于c# - 我可以在 .NET 2.0 或 3.0 中使用扩展方法和 LINQ 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11346554/

相关文章:

c# - 调试到 .net 源对我不起作用

c# - 为什么 SignedCms.ComputeSignature() 方法抛出 "Provider' s 公钥无效”异常?

.net - 如何本地化 DateTime.DayOfWeek?

c# - 使用反射从原始类型确定复杂类型

c# - 通过单击将标记添加到 map

c# - 在 using 语句内部还是外部返回?

.net - NUnit 中的 EqualTo() 和 EquivalentTo() 有什么区别?

.net - 现有连接被远程主机强行关闭

c# - 验证是否存在可用网络连接的最简单方法是什么?

wcf - .net 项目可以发现并使用 WCF 服务吗?