关于c#:我可以在.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运行时添加扩展方法时,我得到错误:

0

但当我试图将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项目中使用它。

只需将以下类添加到项目中,然后就可以开始使用扩展方法:

1
2
3
4
5
6
7
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对象,那么大多数Linq方法实现起来并不复杂。下面是一些Linq-to-Objects替换函数,它们来自我为开始编写的项目。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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到已添加ExtensionAttribute的对象的库(感谢allon guralnek)。