Замыкания в языке C#
От: Тепляков Сергей Владимирович США http://sergeyteplyakov.blogspot.com/
Дата: 12.09.10 09:41
Оценка: 1271 (27)
Статья:
Замыкания в языке C#
Автор(ы): Тепляков Сергей Владимирович
Дата: 13.09.2010
В статье рассказывается внутренняя реализация замыканий (closure) в языке C# и описываются основные подводные камни, с которыми может столкнуться разработчик в своей повседневной деятельности.


Авторы:
Тепляков Сергей Владимирович

Аннотация:
В статье рассказывается внутренняя реализация замыканий (closure) в языке C# и описываются основные подводные камни, с которыми может столкнуться разработчик в своей повседневной деятельности.
Re: Замыкания в языке C#
От: adontz Грузия http://adontz.wordpress.com/
Дата: 12.09.10 10:16
Оценка: +4 -1
Здравствуйте, Тепляков Сергей Владимирович, Вы писали:

Замыкания на переменные цикла зачастую приводят к очень неприятным последствиям, поскольку в этом случае поведение кода начинает отличаться от интуитивно понятного. Данный результат обусловлен двумя причинами: (1) при замыканиях осуществляется захват переменных, а не значений переменных, и (2) в приведенном фрагменте кода, существует один экземпляр переменной i, который изменяется на каждой итерации цикла, а не создается новый экземпляр на каждой итерации. Сложив эти два пункта вместе, мы получим, что будет создан только один объект генерируемого компилятором типа


Дедуктивный метод тут не уместен, поведение просто описано в стандарте, а его логичность или не логичность не может служить докаательством.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re: Замыкания в языке C#
От: Sinix  
Дата: 12.09.10 11:00
Оценка:
Здравствуйте, Тепляков Сергей Владимирович, Вы писали:

я рекомендую почитать сообщения Эрика Липперта (Eric Lippert) ”О вреде замыканий на переменных цикла” и ”Замыкания на переменных цикла. Часть 2””.


Ссылку потеряли

За статью спасибо — вводных статей на русском мало
Re[2]: Замыкания в языке C#
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 12.09.10 16:15
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Ссылку потеряли


Спасибо, поправим.

S>За статью спасибо — вводных статей на русском мало


Так кто ж мешает?
Re: Замыкания в языке C#
От: tyger Россия  
Дата: 22.09.10 04:31
Оценка:
Здравствуйте, Тепляков Сергей Владимирович, Вы писали:

ТСВ>Статья:

ТСВ>Замыкания в языке C#
Автор(ы): Тепляков Сергей Владимирович
Дата: 13.09.2010
В статье рассказывается внутренняя реализация замыканий (closure) в языке C# и описываются основные подводные камни, с которыми может столкнуться разработчик в своей повседневной деятельности.


За статью спасибо.

Но.

В определении
Замыкания (closures) представляют собой фрагменты (блоки) кода, который можно использовать в качестве аргументов функций и методов.
ощущается несогласованность сложноподчиненного предложения: Замыкания ... фрагменты..., которЫЙ ...., возможно имелось в виду "которые".

И неплохо бы в последние примеры добавить примерную интерпритацию кода компилятором, чтобы было наглядно.
Re: Замыкания в языке C#
От: Аноним  
Дата: 06.12.11 19:40
Оценка: 2 (1)
Здравствуйте, Тепляков Сергей Владимирович, Вы писали:

ТСВ>Статья:

ТСВ>Замыкания в языке C#
Автор(ы): Тепляков Сергей Владимирович
Дата: 13.09.2010
В статье рассказывается внутренняя реализация замыканий (closure) в языке C# и описываются основные подводные камни, с которыми может столкнуться разработчик в своей повседневной деятельности.


ТСВ>Авторы:

ТСВ> Тепляков Сергей Владимирович

ТСВ>Аннотация:

ТСВ>В статье рассказывается внутренняя реализация замыканий (closure) в языке C# и описываются основные подводные камни, с которыми может столкнуться разработчик в своей повседневной деятельности.

Честно говоря, статья не очень понравилась. Возможно, потому что я искал не совсем то, что нашел. Я бы сказал, отсутствует общий подход к рассмотрению проблемы, хотя если рассматривать данную статью чисто как знакомство с замыканиями, то пожалуй она имеет место.

Замыкания делаются на внешний контекст, и этим контекстом могут быть не только локальные переменные и аргументы. На самом деле замыкания можно делать на поля (статические и нестатические, в этом случае вместо класса просто создается метод статический или нестатический) и на this (автор говорит, что можно этот случай рассматривать как локальную переменную — абсолютная неправда, здесь также создается экземплярный метод безо всякого класса, т.к. он сам принадлежит этому классу и прекрасно видит ссылку this ). А еще замечательный случай, когда сразу замыкается и поле, и переменная одновременно (тут создается класс с двуми полями — одно под this, чтобы иметь доступ к полю, другое — под переменную).
Re: Замыкания в языке C#
От: help-me  
Дата: 06.04.12 09:03
Оценка:
static Action CreateAction()
{
  int count = 0;
  Action action = () =>
  {
    count++;
    Console.WriteLine("Count = {0}", count);
  };

  return action;
}

static void Main(string[] args)
{
  var action = CreateAction();

  action();
  action();
}


Результат выполнения программы:

Count = 1
Count = 2


А изменится ли результат, если CreateAction переписать как

static Action CreateAction()
{
  int count = 0;
  Action action = () =>
  {
    count++;
    Console.WriteLine("Count = {0}", count);
  };
  int xxx = count;
  xxx++;

  return action;
}

то есть добавить перед return action строки
int xxx = count;
xxx++;
?

Ну и также в статье не описано, для чего вообще были введены замыкания, так как непонятно, зачем захватывать переменные, если можно просто их передать в виде параметра в функцию в делегате.
Re[2]: Замыкания в языке C#
От: hardcase Пират http://nemerle.org
Дата: 06.04.12 09:09
Оценка:
Здравствуйте, help-me, Вы писали:

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


Замыкания нужны для поддержки ФП. Попробуйте написать без замыкания:
public static IEnumerable<int> OnlyGreaterThan(this IEnumerable<int> seq, int value)
{
  return seq.Where(x => x > value); // значение value попадает в замыкание
}
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: Замыкания в языке C#
От: fddima  
Дата: 06.04.12 10:02
Оценка:
Здравствуйте, adontz, Вы писали:

A>Дедуктивный метод тут не уместен, поведение просто описано в стандарте, а его логичность или не логичность не может служить докаательством.

Кстати в C# 5 для foreach теперь будет работать "логично":
Отсюда: Eric Lippert &mdash; Closing over the loop variable considered harmful:

UPDATE: We are taking the breaking change. In C# 5, the loop variable of a foreach will be logically inside the loop, and therefore closures will close over a fresh copy of the variable each time. The "for" loop will not be changed. We return you now to our original article.


PS: И кстати, в статье было бы неплохо это отразить.
Re[3]: Замыкания в языке C#
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 06.04.12 10:53
Оценка:
Здравствуйте, fddima, Вы писали:

A>>Дедуктивный метод тут не уместен, поведение просто описано в стандарте, а его логичность или не логичность не может служить докаательством.

F> Кстати в C# 5 для foreach теперь будет работать "логично":
F>Отсюда: Eric Lippert &mdash; Closing over the loop variable considered harmful:
F>

UPDATE: We are taking the breaking change. In C# 5, the loop variable of a foreach will be logically inside the loop, and therefore closures will close over a fresh copy of the variable each time. The "for" loop will not be changed. We return you now to our original article.


F> PS: И кстати, в статье было бы неплохо это отразить.


Для этого есть другая статья: Замыкания на переменных цикла в C# 5.0
Re[3]: Замыкания в языке C#
От: help-me  
Дата: 09.04.12 10:23
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Здравствуйте, help-me, Вы писали:


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


H>Замыкания нужны для поддержки ФП. Попробуйте написать без замыкания:

H>
H>public static IEnumerable<int> OnlyGreaterThan(this IEnumerable<int> seq, int value)
H>{
H>  return seq.Where(x => x > value); // значение value попадает в замыкание
H>}
H>


А если бы функцию Where реализовали бы не как функцию, принимающую делегат на функцию x => return bool , а как функцию, принимающую делегат на функцию (x, params object[] values) => return bool ? Тогда бы мы могли передавать неограниченное кол-во параметров и вместо захвата требуемого кол-ва переменных, мы могли бы передать их как параметры. Например, код выше заменился бы таким кодом:

public static IEnumerable<int> OnlyGreaterThan(this IEnumerable<int> seq, int value)
{
  return seq.Where((x, value) => x > Convert.ToInt32(value)); 
}

или
public static IEnumerable<int> OnlyGreaterThan(this IEnumerable<int> seq, int value)
{
  return seq.Where((x, new values[1]{value}) => x > Convert.ToInt32(values[0])); 
}



Или, второй вариант, раз уж Microsoft предпочла ограничить нас в кол-ве параметров, передаваемых в делегат для Where: можно написать свой метод-расширение для Where, сделав так, чтобы он принимал нужное нам кол-во параметров, и вызывать метод-расширение, а не тот метод, который в LINQ.
Вот пример этого метода:

public static IEnumerable<int> OnlyGreaterThan(this IEnumerable<int> seq, int value)
{
  return seq.WhereGreaterThan((x, value) => x > value); 
}

//в методе, описанном ниже, могут быть ошибки, так как писал я его от руки прямо в браузере, а не в VS
public static IEnumerable<int> WhereGreaterThan(this IEnumerable<int> seq, delegate Function<int x, int value, return bool>)//объявление делегата описано лишь для примера без точного синтаксиса, так как я не знаю точный синтаксис
{
    IEnumerable<int> list = new List();
    foreach(var item in seq)//проходимся по всему переданному списку, то есть просто сами реализуем то, что реализовано в стандартном Where...
    {
        if(Function())// ...лишь с тем отличием, что вызываем свой делегат с нужной нам сигнатурой
            list.Add(item);
    }
    return list;
}

Или, 3-й вариант, незнаю, насколько он реальный, но можно попробовать наследовать нужный класс и переопределить свою реализвацию Where. Да, все варианты получаются более громоздкими, зато все очевидно и нет никаких скрытых операций, выполняемых компилятором (и, вследствие этого, возможно, влияния на скорость выполнения). То есть, судя по всему, возможность УДАЛЕНИЯ замыканий из языка C# все-же существует без ограничения функционала?
й
Re[4]: Замыкания в языке C#
От: Jack128  
Дата: 09.04.12 10:31
Оценка:
Здравствуйте, help-me, Вы писали:

HM>Или, 3-й вариант, незнаю, насколько он реальный, но можно попробовать наследовать нужный класс и переопределить свою реализвацию Where. Да, все варианты получаются более громоздкими, зато все очевидно и нет никаких скрытых операций, выполняемых компилятором (и, вследствие этого, возможно, влияния на скорость выполнения). То есть, судя по всему, возможность УДАЛЕНИЯ замыканий из языка C# все-же существует без ограничения функционала?


Рекомендую применить данные логические выкладки и к другим элементам языка C#, потом освоить Brainfuck и тогда ты достигнешь нирваны.
Re[4]: Замыкания в языке C#
От: _d_m_  
Дата: 09.04.12 12:14
Оценка:
Здравствуйте, help-me, Вы писали:

HM>А если бы функцию Where реализовали бы не как функцию, принимающую делегат на функцию x => return bool , а как функцию, принимающую делегат на функцию (x, params object[] values) => return bool ? Тогда бы мы могли передавать неограниченное кол-во параметров и вместо захвата требуемого кол-ва переменных, мы могли бы передать их как параметры.


Смысл? Если любая комбинация условий в результате дает true/false
... << RSDN@Home 1.2.0 alpha 5 rev. 1539>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.