Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ламбда-выражения в VB.Net и C#, Области практического применения 
V
    Опции темы
diadiavova
Дата 2.11.2008, 00:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Собственно вопрос в том, для чего нужны ламбда-выражения в указанных языках. Из документации предельно ясно как с ними работать, и что они могут, а чего не могут. Не я сно только одно, для чего их ввели в эти языки. Хотелось бы увидеть конкретный пример того, как использование ламбда-выражений укорачивает код, или упрощает его логику. smile 


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Partizan
Дата 2.11.2008, 00:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 18
Всего: 67



Да для того же, для чего и в остальных языках

Цитата

В программировании лямбда или лямбда-выражения - это безымянная функция, объявляемая по месту ее непосредственного использования.

Замыкание (англ. closure) в программировании — процедура, которая ссылается на свободные переменные в своём лексическом контексте.

Замыкание, так же как и экземпляр объекта, есть способ представления функциональности и данных, связанных и упакованных вместе.

Замыкание — это особый вид функции. Она определена в теле другой функции и создаётся каждый раз во время её выполнения. В записи это выглядит как функция, находящаяся целиком в теле другой функции. При этом вложенная внутренняя функция содержит ссылки на локальные переменные внешней функции. Каждый раз при выполнении внешней функции происходит создание нового экземпляра внутренней функции, с новыми ссылками на переменные внешней функции.

Замыкание связывает код функции с её лексическим окружением (местом, в котором она определена в коде). Лексические переменные замыкания отличаются от глобальных переменных тем, что они не занимают глобальное пространство имён. От переменных в объектах они отличаются тем, что привязаны к функциям, а не объектам.

(с) Wiki

Добавлено через 1 минуту и 3 секунды
diadiavova, по поводу примеров можно глянуть как работает List.Find с использованием лямбд...


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
diadiavova
Дата 2.11.2008, 00:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Цитата(Partizan @  2.11.2008,  00:28 Найти цитируемый пост)
Да для того же, для чего и в остальных языках

То есть?

Что это и как с ним работать мне ясно. Мне не ясно зачем. Насчёт остальных языков - тоже не уверен. В функциональных языках они имеют явно бОльшее значение.
Кроме того, статью в википедии я читал, мне не понятен практический аспект их использования в конкретных языках. Что выиграли эти языки от появления ламбда выражений?

Добавлено через 4 минуты и 14 секунд
Цитата(Partizan @  2.11.2008,  00:28 Найти цитируемый пост)
по поводу примеров можно глянуть как работает List.Find с использованием лямбд

А без лябд он не работает?


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Partizan
Дата 2.11.2008, 00:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 18
Всего: 67



diadiavova, лямбды, я думаю, таки пришли в ООП как раз из функциональных ЯП...
ну вот есть класс List....а теперь посмотрите как можно кастомизировать метод Find с использованием лямбд...

з.ы.  ...пример написать щас сил нет... если до завтра никто не осилит написание примера, то на трезвую голову напишу что-нить...


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
diadiavova
Дата 2.11.2008, 00:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Цитата(Partizan @  2.11.2008,  00:42 Найти цитируемый пост)
если до завтра никто не осилит написание примера, то на трезвую голову напишу что-нить... 

Тогда - до завтра

Добавлено через 6 минут и 42 секунды
Цитата(Partizan @  2.11.2008,  00:42 Найти цитируемый пост)
лямбды, я думаю, таки пришли в ООП как раз из функциональных ЯП.

В этом нет сомнений.
Цитата(Partizan @  2.11.2008,  00:42 Найти цитируемый пост)
ну вот есть класс List....а теперь посмотрите как можно кастомизировать метод Find с использованием лямбд...

Та оно понятно, что файнд, форич, фильтры всевозможные - это хорошо. Только это всё при помощи обычных функций по-моему проще сделать. Здесь ведь при урезанных возможностях всё ещё и в одно выражение надо уместить. В обычной функции таких ограничений нет.

Когда я говорил о примере, я имел в виду не пример использования, это всё понятно. Меня интересует пример, когда при использовании привычных инструментов код получается длинным и/или путанным, а ламбда-выражения решают ту же задачу проще.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
archeg
Дата 2.11.2008, 01:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 612
Регистрация: 6.1.2007
Где: Киев

Репутация: 11
Всего: 27



Чета у меня цитирование в хроме не работает :(

Возьмите любой линк-пример и получите пример лямбда выражений smile Вообще линк без лямбда нереален практически ))

Код

var orders = db.Orders.Where(o => o.CustomerID == "LONEP" && o.OrderDate.Value == now);



Лямбда ничего нового не добавляют! Это самое главное. Это фича языка С# - но не MSIL - значит принципиально ничего нового вы не получите, ведь шарп компилица в мсил. Это для удобности, быстроты набора и читабельности. Вот к примеру верхний кусок кода можно написать и так:
Код

var orders = db.Orders.Where(delegate(Order o)
            {
                if ((o.CustomerID == "LONEP") && (o.OrderDate.Value == now))
                    return true;
                return false;
            });

Правда же, есть разница? Что лучше читаеца и легче пишеться??? А представьте себе этот же код без анонимных делегатов(которые есть тоже, в какой-то мере, лямбда-выражениями), а?  smile

Добавлено @ 01:31
Лямбда плохи когда нужно сделать какое-то особо сложное условие. Но такие вещи достаточно редки. А в более простых случаях - это идеал. Но даж не это главное. Как по мне, так лямбда выражения очень хорошо сочитаються с другими фичами 3.5 шарпа. Их всех очень много и они все-все созданы для линка smile
Особенно мне нравяться анонимные класы:
Код

var orders = db.Orders.Select(o => new {Id = o.ID, o.OrderName, o.OrderDetail});

Сильно упрощают жизнь при разработке (ток не переборщить smile )


Это сообщение отредактировал(а) archeg - 2.11.2008, 01:32


--------------------
ИМХО задница есть универсальный интерфейс. Ибо через задницу можно сделать абсолютно ВСЕ (bash.org.ru)

Дядька всегда можно спросить в аське, если не задалбывать - не откажет smile
И вообще, на самом деле я студент, и ненавижу обращение на "Вы") Тут все свои  ;)
PM MAIL ICQ Jabber   Вверх
diadiavova
Дата 2.11.2008, 01:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Можно то же самое  в в отдельную функцию выделить. Кроме того, в отдельной функции можно и несколько выражений упаковать. А в этом примере разница есть, но она небольшая, и в пользу ламбда-выражений, только потому, что речь идёт о коротком условии. Ввести туда чуть побольше операций и отдельная функция будет куда удобнее.
Цитата(archeg @  2.11.2008,  01:21 Найти цитируемый пост)
Это фича языка С# - но не MSIL - значит принципиально ничего нового вы не получите, ведь шарп компилица в мсил.

Я не пишу на C#, но в VB.Net это тоже есть. А то, что какой-то элемент отсутствует в мсил ещё не говорит о том, что он ничего нового не даёт. Удобство - тоже полезная штука, только вот не ясно в чём оно в конкретном случае. Если мне надо выделить в единый блок каку-то логику - я создаю метод. Здесь же у меня есть возможность описать только одно выражение с ограниченными функциями. 


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
archeg
Дата 2.11.2008, 01:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 612
Регистрация: 6.1.2007
Где: Киев

Репутация: 11
Всего: 27



Цитата(diadiavova @ 2.11.2008,  01:35)
Можно то же самое  в в отдельную функцию выделить. Кроме того, в отдельной функции можно и несколько выражений упаковать. А в этом примере разница есть, но она небольшая, и в пользу ламбда-выражений, только потому, что речь идёт о коротком условии. Ввести туда чуть побольше операций и отдельная функция будет куда удобнее.
Цитата(archeg @  2.11.2008,  01:21 Найти цитируемый пост)
Это фича языка С# - но не MSIL - значит принципиально ничего нового вы не получите, ведь шарп компилица в мсил.

Я не пишу на C#, но в VB.Net это тоже есть. А то, что какой-то элемент отсутствует в мсил ещё не говорит о том, что он ничего нового не даёт. Удобство - тоже полезная штука, только вот не ясно в чём оно в конкретном случае. Если мне надо выделить в единый блок каку-то логику - я создаю метод. Здесь же у меня есть возможность описать только одно выражение с ограниченными функциями.

Новое - имееться ввиду функциональность, а не удобство. Удобство - понятно. Но мсил то один и тот же smile Знач ф-и новой нет.
Выделить в оддельную ф-ю? Ок. Пример из практики... Недавно писал прогу (я ее не дописал, поэтому не покажу smile ) - должна работать с специфичными данными (их не много по количетсову, но много разных типов smile ), кроме того она должна легко переноситься. По-скольку скорость не особо важна, данных не больше мегабайта - выбран формат хмл, для хранения. 
Но самого разнообразия даных очень много, хмл файлов до 10 планировалось. Все это парсить сложно - выбрал XmlToLinq для парса (парсить домом - самоубийство).
Если бы я создавал для каждого условия в коде, оддельный метод, у меня бы появилось больше 100 левых, никому не нужных методов. Все условия простые (для парсинга ничего и не нужно более) - в основном это строка равняеться чему-то. Можно было бы попробовать сбить такие методы, но левая сторона условия строго типизирована - даже не представляю как такое бы выглядело. Какие-то дженерики? Я бы повесился......
Писать такое - самоубийство, поддерживать - еще хуже...

Это сообщение отредактировал(а) archeg - 2.11.2008, 01:44


--------------------
ИМХО задница есть универсальный интерфейс. Ибо через задницу можно сделать абсолютно ВСЕ (bash.org.ru)

Дядька всегда можно спросить в аське, если не задалбывать - не откажет smile
И вообще, на самом деле я студент, и ненавижу обращение на "Вы") Тут все свои  ;)
PM MAIL ICQ Jabber   Вверх
diadiavova
Дата 2.11.2008, 01:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Ну это уже ближе к делу, хотя на пальцах не очень понятно. Упрощённый схематический вариант того, что там было можно представить?


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
archeg
Дата 2.11.2008, 01:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 612
Регистрация: 6.1.2007
Где: Киев

Репутация: 11
Всего: 27



На самом-то деле, компилятор шарпа (и вб) behind the scenes создает этот метод за вас. Просто это скрываецться)

Щас подумаю... ):

Добавлено через 5 минут и 38 секунд
Код

 var functors = doc.Element("FunctionalSchemas").Elements("FunctionalSchema")
                .Where(x => x.Attribute("Name").Value == schemaName).Single()
                .Elements("Functor").Select(x =>
                    new Functor(int.Parse(x.Attribute("Position").Value), schemaName)
                    .SetDescription(x.Element("Description").Value)
                    .SetTonic(bool.Parse(x.Attribute("isTonic").Value))
                    .AddNotations(x.Elements("Text")
                        .Select(y => new KeyValuePair<string, string>(
                            y.Attribute("Notation").Value,
                            y.Value))
                            .ToArray()));
            bool haveError = functors.Select
                (
                x => x
                    .GetSupportedNotationNames()
                    .All(notation => notations.Select(y => y.Name).Contains(notation))
                ).Any(x => x == false);

Вот кусочек кода. Насчитал тут 7 л.в. Тут правда в основном используеться не для отсева, а для создания новых екземпляров, но по-моему - довольно показово.
Объяснить что тут делается или и так понятно?

Это сообщение отредактировал(а) archeg - 2.11.2008, 01:48


--------------------
ИМХО задница есть универсальный интерфейс. Ибо через задницу можно сделать абсолютно ВСЕ (bash.org.ru)

Дядька всегда можно спросить в аське, если не задалбывать - не откажет smile
И вообще, на самом деле я студент, и ненавижу обращение на "Вы") Тут все свои  ;)
PM MAIL ICQ Jabber   Вверх
diadiavova
Дата 2.11.2008, 01:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Кстати насчёт линков, анонимных типов и прочих прелестей вопросов нет. А в VB.Net ещё и XML-литералы имеются smile

Добавлено через 6 минут и 15 секунд
Попробую разобраться, хоть и не силён в шарпе, но пока не надо. Не пойму - переспрошу.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
diadiavova
Дата 2.11.2008, 03:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



В данном случае конечно всё выглядит убедительно, но мне всё-таки этот пример представляется немного искусственным. Здесь в одном выражении многократно вызываются методы, требующие делегатов в качестве аргументов, при этом условия всякий раз формулируются компактно, и использовать в таких ситуациях ламбда-выражения удобно, потомучто это лучше, чем создавать много коротких функций. На практике либо вызовы таких методов как Select, Were и пр. не часты, либо передаваемые им методы в одном выражении не сформулируешь. 
Кроме того XML - вообще не очень убедительный пример из-за обилия инструментов для работы с ним. 

Ну в общем и целом вопрос немного разьяснился, просто появилось много таких методов, которые требуют делегатов и если всё можно сформулировать коротко, то пожалуй, ламбда-выражения могут пригодится, хотя я и не поклонник длинных выражений, которые получаются в результате - их потом анализировать трудно. 


Это сообщение отредактировал(а) diadiavova - 2.11.2008, 04:04


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
archeg
Дата 2.11.2008, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 612
Регистрация: 6.1.2007
Где: Киев

Репутация: 11
Всего: 27



Цитата(diadiavova @ 2.11.2008,  03:42)
В данном случае конечно всё выглядит убедительно, но мне всё-таки этот пример представляется немного искусственным. Здесь в одном выражении многократно вызываются методы, требующие делегатов в качестве аргументов, при этом условия всякий раз формулируются компактно, и использовать в таких ситуациях ламбда-выражения удобно, потомучто это лучше, чем создавать много коротких функций. На практике либо вызовы таких методов как Select, Were и пр. не часты, либо передаваемые им методы в одном выражении не сформулируешь. 
Кроме того XML - вообще не очень убедительный пример из-за обилия инструментов для работы с ним. 

Ну в общем и целом вопрос немного разьяснился, просто появилось много таких методов, которые требуют делегатов и если всё можно сформулировать коротко, то пожалуй, ламбда-выражения могут пригодится, хотя я и не поклонник длинных выражений, которые получаются в результате - их потом анализировать трудно.

Никак не искуственно, вытянул кусок кода из проекта про который я говорил. Возьму за пример линк:
1) LinqToXML. При разборе хмл, возникают условия зачастую проверки имени (просто строка == строке), особенно если хмл используеться как конфиг файл. Про изобилие тулсами для анализа хмл - первый раз слышу, всегда думал что до линка все разработчики мучаились через дом. Может что и есть, но не настолько удобное как линк. 
2) LinqToSQL. Полностью забыл про него. Тут специфика немного другая, постараюсь рассказать более подробно:
CLR при анализе линк-запроса, должен его превратить в запрос вида SQL. То есть если напишем вот такое:
Код

var result = table.Where(a => a.SomeString.Contains("hello")).Select(a => a.Name);

CLR преобразует это в:
Код

select a.Name from table a where a.SomeString like '%hello%'


Допустим в Where понадобилось вставить более сложное условие. Вставить условие, которое состоит из ендов и оров - без проблем. И выглядить красиво (если отформатировать smile )
Код

var result = table.Where(a => 
               (
              a.SomeString.Contains("hello") || a.SomeString.Contains("hi")
               ).Select(a => a.Name);

Допустим нужно вставить специфическое условие, которое не под силу лямбда. Например:
Код

var result  = table.Where(delegate(row a)
{
     longint bytecode = 0;
     for (int i=0; i<a.SomeString.Length; i++)
     {
         bytecode += (byte)a.SomeString[i];
     }
     return (bytecode % 2) == 0;
}).Select(a => a.Name);

Получим - да, нам пришлось отказаться от лямбда выражений. Посмотрим SQL запрос. Мы там увидим:
Код

select a.Name from table

Конечно же, линктусиквел не знает как транслировать такое условие в скл. И попытаеться програмно его обработать. Значит в конечном итоге нам прийдеться отказаться от такого условие (к примеру перенести ответственность на базу, сделав вьюху) - и использовать лямбда smile

P.S. На самом то деле, лямбда выражения полностью заменяют анонимные делегаты (это они и есть). И в них можно написать что захочешь. К примеру:
Код

var result  = table.Where((row a) =>
{
     longint bytecode = 0;
     for (int i=0; i<a.SomeString.Length; i++)
     {
         bytecode += (byte)a.SomeString[i];
     }
     return (bytecode % 2) == 0;
}).Select(a => a.Name);

Пару аргументов тоже можно использовать. Только такой вид записи ничем не отличается от анонимных делегатов - мне кажеться что лучше использовать их в таком случае.

Добавлено через 2 минуты и 15 секунд
Идеалогия в том что если нельзя условие сформулировать в одном выражении - то гарантия что LinqToSql не сможет его правильно транслировать - оно слишком сложное.




--------------------
ИМХО задница есть универсальный интерфейс. Ибо через задницу можно сделать абсолютно ВСЕ (bash.org.ru)

Дядька всегда можно спросить в аське, если не задалбывать - не откажет smile
И вообще, на самом деле я студент, и ненавижу обращение на "Вы") Тут все свои  ;)
PM MAIL ICQ Jabber   Вверх
diadiavova
Дата 2.11.2008, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 31
Всего: 142



Цитата(archeg @  2.11.2008,  12:39 Найти цитируемый пост)
Про изобилие тулсами для анализа хмл - первый раз слышу, всегда думал что до линка все разработчики мучаились через дом. Может что и есть, но не настолько удобное как линк. 

Ну про линк я не спорю, только через дом обработка не такая мучительная. Например для того, чтобы отобрать узлы, удовлетворяющие определённому условию, достаточно просто вызвать метод System.Xml.XmlNode.SelectNodes. Единственная проблема написать условие отбора на XPath. Да и простой рекурсивный обход узлов зачастую выглядит куда более понятно, чем такие пространные выражения как в предыдущем примере.

Цитата(archeg @  2.11.2008,  12:39 Найти цитируемый пост)
LinqToSQL. Полностью забыл про него. 

Ну это - пожалуй. Наверное в этом всё дело. Просто я думал, что они вообще дают какие-то возможности, которые я не использую и что-то теряю от этого. 

Всем спасибо. Вопрос закрываю.

Это сообщение отредактировал(а) diadiavova - 2.11.2008, 14:59


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Jamon
Дата 7.11.2008, 20:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 1.9.2007

Репутация: нет
Всего: нет



насколько я понимаю, семантика лямбда выражений активно используется в linq, а это уже довольно большое нововведение в язык
не заметил последний пост..

Это сообщение отредактировал(а) Jamon - 7.11.2008, 20:55
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0603 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.