扩展方法直到 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)。