Могу ли я использовать методы расширения и LINQ в.NET 2.0 или 3.0?
Когда я пытаюсь добавить метод расширения с использованием среды выполнения.NET 2.0 или 3.0, я получаю сообщение об ошибке:
Невозможно определить новый метод расширения, так как не найден требуемый компилятору тип 'System.Runtime.CompilerServices.ExtensionAttribute'. Вам не хватает ссылки на System.Core.dll?
Но я не могу найти System.Core в списке доступных ссылок, когда пытаюсь добавить его в проект. Что мне нужно сделать, чтобы иметь возможность использовать методы расширения и, в свою очередь, включить LINQ в моих проектах?
1 ответ
Методы расширения не были добавлены в.NET до 3.5. Однако это было не изменение 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;
}
}
Библиотека с полной повторной реализацией LINQ to Objects с ExtensionAttribute
уже добавлено в можно найти в проекте LinqBridge (спасибо Allon Guralnek).