Friday, January 3, 2014

Расширяем возможности .NET 2.0

Здравствуйте, уважаемые читали моего блога. В первой за 2014 год статье речь пойдет о возможностях языка C# для написания программ под .NET Framework 2.0. Если Вам не приходится писать код хоть изредка для .NET Framework 2.0, для Вас этот материал, возможно, будет интересным для ознакомления. У современного C# программиста, который программирует на .NET Framework 4.0/4.5, начинается нервная дрожь, когда ему приходится что-то писать под второй фреймворк, и такую реакцию разработчиков можно понять. Вам нужно отказаться от extension methods, лямбда-выражений, linq и других возможностей, которые появились в C# 3.0. Для меня ситуация в этом плане была такой же. Поэтому я предвзято отношусь ко второму фреймворку после использования более поздних версий. Было бы здорово в .NET Framework 2.0 иметь возможность использовать хотя бы часть возможностей C# 3.0 с поддержкой лямбда-выражений и других возможностей, которые появились в нем. Об этих возможностях можно посмотреть в статье "Тенденции разработки прикладных программ на языке C#". Пожалуй, пришло время Вас обрадовать. Вы можете использовать часть возможностей, доступных с C# 3.0, во втором фреймворке. Для этого придётся использовать небольшой "хак", который позволит использовать возможности C# 3.0, вместо C# 2.0. И самое интересное заключается в том, что Ваше приложение будет работать под вторым фреймворком без проблем. Extension methods и query expression требуют специальный атрибут, который определен в .NET 3.5. Но это не составляет проблему для того, чтобы переопределить этот атрибут самому. Вот как это выглядит:
namespace System.Runtime.CompilerServices
{
    [AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
    public class ExtensionAttribute : Attribute
    {
    }
}
Теперь у Вас доступна возможность использовать расширяемые методы (extension methods), потому что доступно использование ключевого слова this для данных методов. Пример использования:
class Program
{
    static void Main(string[] args)
    {
        string test = null;
        Console.WriteLine(test.CheckNullString());
        Console.ReadLine();
    }
}

public static class StringExtension
{
    public static bool CheckNullString(this string value)
    {
        return value == null;
    }
}
Этот прогресс не может не радовать. Правда, этого маловато для того, чтобы использовать возможности LINQ. Мы можем открыть MSDN и перенести с последней версии фреймворка реализацию делегатов Action и Func к себе.
public delegate void Action();
public delegate void Action<T1, T2>(T1 arg1, T2 arg2);
public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
public delegate void Action<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
public delegate TResult Func<TResult>();
public delegate TResult Func<T, TResult>(T arg);
public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
public delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);
public delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);

По желанию можно также перенести делегат Predicate. Дальше если Вы хотите использовать возможности методов LINQ, нужно их реализовать самим. К счастью, автор известной книги Joseph Albahari, C# 5.0 in a Nutshell написал библиотеку LINQBridge, которая позволяет использовать часть возможностей из LINQ to Objects. Для этого нам нужно загрузить либо библиотеку по приведенной ссылке, либо исходный код, который позволяет это все использовать. Посмотрите, как это будет выглядеть.
private static void Main(string[] args)
{
    var mass = new [] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    var result = mass.Where(number => number%2 == 0).Select(number => number + "$");
    foreach (var number in result)
    {
        Console.WriteLine(number);
    }

    var query =
        from n in mass
        where n > 5
        orderby n
        select n * 10;

    foreach (var number in query)
    {
        Console.WriteLine(number);
    }
    Console.ReadLine();
}
Нам доступна как точечная нотация, так и нотация на основе выражений.
К сожалению, нам остались недоступны деревья выражений. Поскольку деревья выражений (expression trees) являются частью .NET 3.5, и эту часть нельзя просто так перенести как  LINQBridge, который, по сути, заново реализует LINQ to Objects.  

Итоги
Благодаря таким гуру, как Джон Скит и Джозеф Албахари, я узнал о возможности использования в .NET 2.0 тех возможностей языка C#, которые успел полюбить, начиная с C# 3.0. Для тех, кто знаком с работой Джона Скита через прочтение его книг или отслеживание его "творчества" на stackoverflow, эта статья не расскажет ничего нового. Если Вы не знакомы с книгами данного автора, рекомендую посмотреть одну из его книг "C# in Depth", которой, уверен, будете приятно удивлены. Надеюсь, что Вы ее прочтёте и она, как и для меня, также станет одной из любимых книг по языку C#.

Источники

No comments:

Post a Comment