Чем анонимные делегаты лучше наследования?
От: RUMACTEP Россия  
Дата: 22.09.06 09:18
Оценка:
Я начал использовать преимущества C# 2.0, а именно анонимными делегатами
Допустим у нас есть такой код
/// какой-то интерфейс 
public interface IFoo {
    void DoSomething(int something);
}

/// класс-пользователь интерфейса IFoo
public class FooUser {
    public void UseFoo(IFoo foo) {
        foo.DoSomething(0);
    }
}


можно попробовать классический способ — сделат несколько наследников от IFoo
/// вариант с подклассами- наследниками от интерфеса IFoo
public class Example_WithSubClasses {
    // класс-наследник 1
    public class Foo1 : IFoo {
        public void DoSomething(int something) {
            // делаем это первым способом
        }
    }

    // класс-наследник 2
    public class Foo2 : IFoo {
        public void DoSomething(int something) {
            // делаем это по-другому
        }
    }

    // пример использования
    public void Example() {
        IFoo foo;
        FooUser user = new FooUser();

        // делаем это первым способом
        foo = new Foo1();
        user.UseFoo(foo);

        // делаем это по-другому
        foo = new Foo2();
        user.UseFoo(foo);
    }
}


Но каждый раз писать новый наследник лениво. Можно написать один наследник на все случаи жизни, используя второй способ
/// вариант с анонимными делегатами
public class Example_WithDelegates {
    // класс-наследник, он будет один на все случаи
    public class FooDelegate : IFoo {
        public delegate void DoSomethingDelegate(int something);

        private DoSomethingDelegate _doSomething;

        // в конструктор передаем делегат, который будет вызываться при вызове IFoo.DoSomething()
        public FooDelegate(DoSomethingDelegate doSomething) {
            _doSomething = doSomething;
        }

        // IFoo.DoSomething()
        public void DoSomething(int something) {
            _doSomething(something);
        }
    }

    // пример использования
    public void Example() {
        FooUser user = new FooUser();

        user.UseFoo(new FooDelegate(delegate(int something) {
                                        // делаем это первым способом
                                    }));

        user.UseFoo(new FooDelegate(delegate(int something) {
                                        // делаем это по-другому
                                    }));
    }
}


Вопрос: какой способ лучше и понятнее? Не будет ли второй вариант труден для понимания?
Правило наименьшего удивления: Программа должна работать так, чтобы это вызывало наименьшее удивление у пользователя.
Построй свой мини-горд на http://rumactep.myminicity.com/
Re: Чем анонимные делегаты лучше наследования?
От: hugo Австрия  
Дата: 22.09.06 09:51
Оценка:
Здравствуйте, RUMACTEP, Вы писали:

Не совсем хороший пример, ИМХО... Больше похоже на даунгрейд рефакторинга. На мой взгляд, это замена некоего патерна, который присутствовал в виде конкретной реализации интерфейса IFoo, размазыванием кода по другому классу.
Вообще-то, анонимные делегаты — это хорошо, в умелых руках
Re: Чем анонимные делегаты лучше наследования?
От: _FRED_ Черногория
Дата: 22.09.06 09:52
Оценка:
Здравствуйте, RUMACTEP, Вы писали:

RUM>Вопрос: какой способ лучше и понятнее?


По большому счёту — только в возможности расширить интерфейс (добавить ещё один метод\свойство\событие).

RUM>Не будет ли второй вариант труден для понимания?


Не должен, хотя кому-как, но, в связи с надвигающимся уклоном в сторону функционального стиля, не дожен быть труден.
... << RSDN@Home 1.2.0 alpha rev. 652>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re: Чем анонимные делегаты лучше наследования?
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.09.06 06:07
Оценка:
Здравствуйте, RUMACTEP, Вы писали:

RUM>Я начал использовать преимущества C# 2.0, а именно анонимными делегатами


1. Нет никаких анонимных делегатов. Есть анонимные методы. Это в МС шутники юмора завеслись. Ради экономии ключевых слов повторно использовали (бездумно) для этих целей ключевое слово delegate.

2. Анонимные методы намного более удобный инструмен для специализации алгоритмов и т.п. "кусками логики". Правда хранить их в полях не лучшая идея. Намного удлобнее передавать их в качестве параметра. Это получается короче, яснее и гибче.

3. Кайф анонимных методов в том, что они допускают лексические замыкания. То есть в анонимном методе можено напрямую использовать любую переменную или фунцию видимую из точки его объявления. Это позволяет порождать очень простой в понимании и гибкий код.

4. В большинстве случаев при предаче анонимного метода в качестве парамтера нет нужды явно создавать делегат. C# сам приведет метод к нужному делегату. Его тип он выведет из типа параметра или переменной.

В C# 3.0 идея анонимных методов будет развита еще сильнее. Появятся лямбды с намного более крактим синтаксисом. И в купе с новой библиотекой Linq они позволят существенно сократить объем кода при работе с коллекциями и БД.

RUM>Но каждый раз писать новый наследник лениво. Можно написать один наследник на все случаи жизни, используя второй способ

RUM>
RUM>/// вариант с анонимными делегатами
RUM>public class Example_WithDelegates {
RUM>    // класс-наследник, он будет один на все случаи
RUM>    public class FooDelegate : IFoo {
RUM>        public delegate void DoSomethingDelegate(int something);

RUM>        private DoSomethingDelegate _doSomething;

RUM>        // в конструктор передаем делегат, который будет вызываться при вызове IFoo.DoSomething()
RUM>        public FooDelegate(DoSomethingDelegate doSomething) {
RUM>            _doSomething = doSomething;
RUM>        }

RUM>        // IFoo.DoSomething()
RUM>        public void DoSomething(int something) {
RUM>            _doSomething(something);
RUM>        }
RUM>    }

RUM>    // пример использования
RUM>    public void Example() {
RUM>        FooUser user = new FooUser();

RUM>        user.UseFoo(new FooDelegate(delegate(int something) {
RUM>                                        // делаем это первым способом
RUM>                                    }));

RUM>        user.UseFoo(new FooDelegate(delegate(int something) {
RUM>                                        // делаем это по-другому
RUM>                                    }));
RUM>    }
RUM>}
RUM>


А смыслв в этой обертке? Смотри как красиво можно жить передавая все что нужно в качестве парамтера.
Например:
using System;
using System.Collections.Generic;
using System.Text;

class Program
{
    static void Main()
    {
        int max = 50;
        List<int> list = new List<int>(new int[] { 1, 200, 3, 4, 5, 6, 78, 190 });

        Console.WriteLine(ToString(Filter(list, delegate(int x) { return x < max; }), ", ")); // анонимный метод замыкается на перменную max!
    }

    static string ToString<T>(IEnumerable<T> seq, string separator)
    {
        StringBuilder sb = new StringBuilder();

        foreach (T value in seq)
        {
            sb.Append(value);
            sb.Append(separator);
        }

        if (sb.Length > 0)
            sb.Length -= separator.Length;

        return sb.ToString();
    }

    static IEnumerable<T> Filter<T>(IEnumerable<T> seq, Predicate<T> predicate)
    {
        foreach (T value in seq)
            if (predicate(value))
                yield return value;
    }
}
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Чем анонимные делегаты лучше наследования?
От: Аноним  
Дата: 23.09.06 08:40
Оценка:
Console.WriteLine(ToString(Filter(list, delegate(int x) { return x < max; }), ", ")); // анонимный метод замыкается на перменную max!

Подскажите, а как эту строку реализовать на VB.Net ?


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[2]: Чем анонимные делегаты лучше наследования?
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.09.06 21:44
Оценка:
Здравствуйте, DedMoroz, Вы писали:

DM>
Console.WriteLine(ToString(Filter(list, delegate(int x) { return x < max; }), ", ")); // анонимный метод замыкается на перменную max!

DM>Подскажите, а как эту строку реализовать на VB.Net ?

Боюсь, что пока никак. Возмоно в следующей версии в VB.Net все таки добавят лямбды и тогда это можно будет повторить на нем.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Чем анонимные делегаты лучше наследования?
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.09.06 06:39
Оценка:
Здравствуйте, RUMACTEP, Вы писали:

RUM>Вопрос: какой способ лучше и понятнее? Не будет ли второй вариант труден для понимания?

Оба способа хороши. К примеру, в ASP.NET 2.0 есть такой интерфейс — ITemplate.
Можно честно реализовывать его в своем классе.
А есть класс CompiledTemplateBuilder : ITemplate.

Он очень удобен, когда нужен "одноразовый" шаблон.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Чем анонимные делегаты лучше наследования?
От: Аноним  
Дата: 25.09.06 08:34
Оценка:
Посмотрел Рефлектором как реализуется строка: yield return value ...
и выпал в осадок!
Компилятор генерит целый класс! Почему бы на VB так ни сделать?
Блин, дискриминация какая то!!!




данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.