Feel Good.

20 апреля 2010

Extension Methods как «Синтаксический сахар»

Решил начать собирать на этой страничке интересные и полезные решения на базе Extension Methods, которые облегчают процесс написания кода, или другими словами «Синтаксический сахар».

Приведу некоторые из них:
  1. На днях, изучал исходники проекта KIGG и встретил там удобный вариант форматирования строки, взамен String.Format:

    public static string FormatWith(this String target, params object[] args)

    {

        return string.Format(target, args);

    }


    Пример:

    string line = "Hello, {0}".FormatWith("Ilya");



  2. Преобразование строки в тип перечисления (Enum):

    public static TEnum CastToEnum<TEnum>(this string input, bool ignoreCase)

    {

        return (TEnum)Enum.Parse(typeof(TEnum), input, ignoreCase);


    Пример:

    DayOfWeek day = "Sunday".CastToEnum<DayOfWeek>(true);


    Можно добавить значение по-умолчанию в сигнатуру метода.

  3. Удобное приведение к типу, взамен as и is:

    public static T As<T>(this object obj)

        where T : class

    {

        return obj as T;

    }

     

    public static T Like<T>(this object obj)        

    {

        return (T)obj;

    }

     

    public static bool Is<T>(this object obj)

    {

        return obj is T;

    }


    Пример:

    object o1 = true;

    bool isbool = o1.Is<Boolean>();

     

    object o2 = "abc";

    string str = o2.As<String>();

     

    object o3 = 123;

    Int32 num = o3.Like<Int32>();



  4. В одном из Mock фреймворков (Rocks) встретил интересную запись цикла for:

    public static void Times(this int count, Action<int> action)

    {

        for (int i = 0; i < count; i++)

            action(i);

    }


    Пример:

    5.Times(i => Console.WriteLine(i));



  5. Проверка, что строка непустая:

    public static bool IsNullOrEmpty(this string self, bool trim)

    {

        if (self == null)

            return true;

     

        if (trim)

            self = self.Trim();

     

        return string.IsNullOrEmpty(self);

    }


    Пример:

    bool empty = "  ".IsNullOrEmpty(true);


    Кстати, для null тоже работает, хотя и вводит в заблуждение:

    string nul = null;

    // Вернет true

    bool isnul = nul.IsNullOrEmpty(true);


  6. .NET Extensions - Extension Methods Library
  7. EventHandler extention
  8. Продолжение следует...Буду благодарен, если Вы предложите в комментариях свои решения.

11 комментариев:

  1. из того же KIGG еще полезная вещь
    public static string NullSafe(this string target)
    {
    return (target ?? string.Empty).Trim();
    }

    ОтветитьУдалить
  2. Я часто еще встречаю MD5 расширение для типа String.

    ОтветитьУдалить
  3. public static class StreamExtensions
    {
    public static byte[] ToArray(this Stream source)
    {
    if (source is MemoryStream)
    {
    return ((MemoryStream)source).ToArray();
    }

    if (source.CanSeek)
    {
    var oldPosition = source.Position;
    source.Position = 0;
    var result = new byte[source.Length];
    source.Read(result, 0, result.Length);
    source.Position = oldPosition;
    return result;
    }

    var buffer = new byte[BufferSize];
    int read;
    var resultStream = new MemoryStream();
    while ((read = source.Read(buffer, 0, BufferSize)) > 0)
    {
    resultStream.Write(buffer, 0, read);
    }

    return resultStream.ToArray();
    }

    public static Stream ToStream(this byte[] source)
    {
    return new MemoryStream(source);
    }

    private const int BufferSize = 128 * 1024;

    public static void WriteTo(this Stream source, Stream target)
    {
    var buffer = new byte[BufferSize];
    var oldPosition = -1;
    if (source.CanSeek)
    {
    oldPosition = source.Position;
    source.Position = 0;
    }

    int read;
    while((read = source.Read(buffer, 0, BufferSize)) > 0)
    {
    target.Write(buffer, 0, read);
    }

    if (oldPosition != -1)
    {
    source.Position = oldPosition;
    }
    }
    }

    ОтветитьУдалить
  4. Еще, как вариант форматирования денежных сумм, можно так:

    public static string ToCurrency(this decimal money)
    {
    return string.Format("{0:C}", money);
    }

    ОтветитьУдалить
  5. ForEach, о целесообразности которого идут споры:
    public static void ForEach(this IEnumerable source, Action action)
    {
    foreach (var item in source)
    {
    action(item);
    }
    }

    public static void ForEach(this IEnumerable source, Action action, TArg arg)
    {
    foreach (var item in source)
    {
    action(item, arg);
    }
    }

    public static void ForEach(this IEnumerable source, Action action, TArg1 arg1, TArg2 arg2)
    {
    foreach (var item in source)
    {
    action(item, arg1, arg2);
    }
    }

    Маленькие вкусности для коллекций:

    public static void Truncate(this List source, int count)
    {
    source.RemoveRange(count, source.Count - count);
    }

    public static void AddRange(this ICollection source, IEnumerable items)
    {
    items.ForEach(source.Add);
    }

    Формирование последовательностей на-лету:

    public static IEnumerable Enumerate(this T value)
    {
    yield return value;
    }

    public static IEnumerable Enumerate(this T value1, T value2)
    {
    yield return value1;
    yield return value2;
    }

    public static IEnumerable Enumerate(this T value1, T value2, T value3)
    {
    yield return value1;
    yield return value2;
    yield return value3;
    }

    public static IEnumerable Enumerate(this T value1, T value2, T value3, T value4)
    {
    yield return value1;
    yield return value2;
    yield return value3;
    yield return value4;
    }

    public static IEnumerable Append(this IEnumerable source, T value)
    {
    return source.Concat(value.Enumerate());
    }

    public static IEnumerable Append(this IEnumerable source, T value1, T value2)
    {
    return source.Concat(value1.Enumerate(value2));
    }

    public static IEnumerable Append(this IEnumerable source, T value1, T value2, T value3)
    {
    return source.Concat(value1.Enumerate(value2, value3));
    }

    Имя "Enumerate" возможно не очень здесь подходит, просто хотелось имя покороче

    ОтветитьУдалить
  6. Парсер зохавал все угловые скобки. Надеюсь и так понятно будет

    ОтветитьУдалить
  7. Не совсем понимаю, почему o1.Is() удобнее, чем o1 is boolean? По-моему, совершенно лишнее.

    ОтветитьУдалить
  8. @SKINDER

    На то он и "синтаксический сахар", что без него можно обойтись).

    Но например:
    Вместо (o1 is boolean).ToString()
    можно так o1.Is<Boolean>().ToString()
    Получается нечто fluent interface.

    ОтветитьУдалить
  9. вот,часто юзаю
    /// Выполняет функцию case1 если src не null, иначе выполняет функцию case2
    public static R Map(this T src, Func case1, Func case2)
    {
    return src != null
    ? case1(src)
    : case2(src);
    }

    /// Выполняет функцию если src не null, иначе возвращает def
    public static R Map(this T src, Func selector, R def)
    {
    return src != null
    ? selector(src)
    : def;
    }

    /// Выполняет функцию если src не null
    public static R Map(this T src, Func selector)
    {
    return src != null
    ? selector(src)
    : default(R);
    }

    el.Attribute("displayName").Map(v => result += string.Format("\r\n\t {0}", v.Value));

    ОтветитьУдалить
  10. @anemon
    Спасибо, интересное решение. Можно даже назвать метод CaseByNull или что-то в этом роде.

    ОтветитьУдалить
  11. Specifically, the sum of all the person losses is used to fund the massive jackpots. Therefore, to provide enticing jackpots, many gamers must lose all of their Tuesday night bankroll. Choose among forty exciting table video games, with friendly sellers and an environment of unparalleled comfort. Try your hand at favorites such as Blackjack or Roulette, or take a shot at Craps, Head’s Up Hold’em, 온라인카지노 and Flop Poker.

    ОтветитьУдалить