metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2010-08-14 06:02 pm

C# и глюки с замыканиями

Я где-то сошел с ума, но с ходу не соображу где.

Есть такой код с замыканиями:

  class Program {

    delegate void ZeroArityFunc();

    static string[] testData=new string[] { "a", "b", "c", "d", "e", "f" };

    static void Main(string[] args) {
      List list = new List();
      foreach(string s in testData) {
        ZeroArityFunc f = () => Console.Write(s); //создаем лямбду и присваиваем ее f
        list.Add(f);
      }

      foreach(ZeroArityFunc a in list) {
        a();
      }

    }
  }



Т.е. я пытаюсь сделать следующее: создать список функций без параметров, которые при вызове будут выдавать результаты от a до f. Это вообще имитация другого, рабочего кода, но суть та же самая.

А теперь внимание, ШИЗА: этот код выдает "f f f f f f", а не то, что я от него хочу ("a b c d e f"). Т.е. делегаты в списке каким-то чудесным образом начинают ссылаться не 6 разных экземпляров замыканий, а на один.

Что-то мне это начинает необъяснимо напоминать недавний пост [livejournal.com profile] alexclear про JavaScript, я сейчас для смеха попробую тамошний workaround.

PS: Жопа, workaround оттуда сработал. В кошмарном сне бы такое не привиделось, что непонятный пост про совершенно неизвестный мне язык через неделю окажется пригодным в работе.

PPS: Оказывается, известная шиза - переменная цикла s объявлена один раз и до цикла, и замыкается оно на нее.

[identity profile] w00dy.livejournal.com 2010-08-14 07:44 pm (UTC)(link)
ребе, вас var и System.Action пользовать не учили?

[identity profile] metaclass.livejournal.com 2010-08-14 07:48 pm (UTC)(link)
У меня часть кода со времен 2003 студии и 1.1 дотнета живет.
А это все счастье только в 3.5 появилось. К тому времени я уже половину всех этих типов сам написал :)

[identity profile] w00dy.livejournal.com 2010-08-14 08:10 pm (UTC)(link)
Никто не мешает пользовать это всё в 2.0, вы же вот пользуете лямбды, а var и Action - нет.

[identity profile] metaclass.livejournal.com 2010-08-14 08:18 pm (UTC)(link)
В компиляторе 2005 студии не было этого дела, поэтому по привычке использую то что помню :)
Про System.Action я вообще не знал, а var использую только когда типы слишком заебенные чтобы их руками писать, или когда у них вообще тип автоматический.

[identity profile] w00dy.livejournal.com 2010-08-14 08:47 pm (UTC)(link)
Тогда ещё узнайте о System.Func и клоны. А var - имхо если и пользовать, то везде. А тип пусть выводит компилятор, студия и всякие тулзени аля R# и прочие, не барское это дело.

[identity profile] metaclass.livejournal.com 2010-08-14 08:57 pm (UTC)(link)
System.Func я знаю.
Вот чего я не знаю так это как синоним типа в C# написать и меня это бесит :)

[identity profile] w00dy.livejournal.com 2010-08-14 10:57 pm (UTC)(link)
а зачем вам синонимы? Мне лично ни разу не требовалось что-то такое.

[identity profile] feorex.livejournal.com 2010-08-14 11:26 pm (UTC)(link)
А что такое синоним типа? Алиас?
using int = System.Int32;
не?