А в C# 3.0 тоже так?
что должен делать вот такой код?:
падать по Core dumped?
void Main
{
if(..)
{
int i;
Calculate(out i);
}
Console.ReadLine;
}
void Calculate(out i)
{
Thread thread = new Thread(delegate
{
Thread.Sleep(TimeSpan.FromSeconds(10;
i = 5;
});
thread.Start;
}
т.е. основная проблема в том, что out/ref параметры не имеют смысла вне текущего контекста,
а anonymous block как раз может быть передан за текущий контекст.
Я уж не говорю о том, что такую функциональность можно получить в любом случае через внешние глобальные переменные.
А вопрос возник примерно из такого желания:
class SomeForm
{
SomeForm
{
...
button1.Clicked += validate_bitmap_button(textPathTop, out bmpTop);
button2.Clicked += validate_bitmap_button(textPathMiddle, out bmpMiddle);
button3.Clicked += validate_bitmap_button(textPathBottom, out bmpBottom);
...
}
EventHandler validate_bitmap_button(TextBox path, out Bitmap bmp)
{
return new EventHandler(delegate(object sender, EventArgs e)
{
try {
bmp = ValidateAndLoadBitmap(path.Text);
// Чтобы сделать validate, bitmap надо загрузить. Зачем потом грузить его еще раз?
} catch(FileIsInvalidForOurTask) {
//...
}
});
}
}
В том же Perl'е такое не считается "не имеющим смысла вне текущего контекста". Это удобно.
// Чтобы сделать validate, bitmap надо загрузить. Зачем потом грузить его еще раз?А зачем каждый раз при клике грузить битмап?
Ты уводишь разговор в сторону. Существует еще много случаев, когда такая функциональность удобна.
P.S. Вспоминается http://www.paulgraham.com/accgen.html
Ну и любопытство: F#/Nemerle этого обходить тоже не умеют?а там есть out-параметры?
Понятия не имею. Подозреваю, что там что-то такое можно организовать.Ну и любопытство: F#/Nemerle этого обходить тоже не умеют?а там есть out-параметры?
Наверное, и в F# так же.
Это - явное указание компилятору, что с такой переменной нужно поступать по-другому. Наверное, C# пытается локальные переменные размещать на стеке.
По условаию задачи при клике надо сделать validate. Для того чтобы его сделать, bitmap надо загрузить.Я просто хочу сказать, что вовсе не обязательно загружать картинку каждый раз при клике.
Ты уводишь разговор в сторону. Существует еще много случаев, когда такая функциональность удобна.
P.S. Вспоминается http://www.paulgraham.com/accgen.html
По ссылке я не нашёл этой функциональности. Там обычный closure.
Ты уводишь разговор в сторону.Возможно, но, имхо, если реализовать это в java-стиле (где нет делегатов и out-параметров то будет даже лучший дизайн.
Я просто хочу сказать, что вовсе не обязательно загружать картинку каждый раз при клике.Тьфу привязался. Ну по условию задачи так. Это не "нравится - не нравится". В любом случае, я просто привел пример, когда out параметр в anonymous delegate имеет смысл. И у меня особого желания мусолить насколько это политкорректно - использовать такие конструкции - нет. Вопрос же простой:
А в C# 3.0 тоже так?
Возможно, но, имхо, если реализовать это в java-стиле (где нет делегатов и out-параметров то будет даже лучший дизайн.А можно пример, как это сделать in java way? Я java знаю на уровне читателя, не писателя.
По ссылке я не нашёл этой функциональности. Там обычный closure.В C# 2.0 closure поддерживается только в виде anonymous delegates, или я что-то не понимаю?
Ну по условию задачи так.То есть я кликнул на кнопку один раз, а когда кликал во второй - картинку уже стёрли? А где она нужна, чтобы "не загружать её во второй раз"? Ты описываешь какой-то изощрённый вариант closure.
class Accumulators {
string s1, s2, s3;
Accumulators {
button1.Click += accumulate_to(out s1);
button2.Click += accumulate_to(out s2);
button3.Click += accumulate_to(out s3);
button4.Click += new EventHandler(delegate(object sender, EventArgs e)
{
MessageBox.Show(string.format("s1: {0}, s2: {1}, s3: {2}", s1, s2, s3;
});
}
EventHandler accumulate_to(out string s) {
return new EventHandler(delegate(object sender, EventArgs e {
s += "Yo!";
}
}
}
Никаких изощрений. Ну что ты к файлам привязался? Ну хочешь, пусть так будет:Вот, теперь более понятно. Просто по ссылке описано замыкание на параметр, а сам параметр при этом не трогают. Ты же хочешь изменять содержимое ссылки. Да, придётся оборачивать изменяемую ссылку.
а зачем надо писать accumulate_to(out s1 когда в прототипе уже есть out?
The out keyword causes arguments to be passed by reference. This is similar to the ref keyword, except that ref requires that the variable be initialized before being passed. To use an out parameter, both the method definition and the calling method must explicitly use the out keyword.
так основной вопрос: ни что делать, когда все хорошо, а что делать если все-таки эта переменная разрушена?
т.е. ты хочешь, чтобы .net портил память?
сборщик мусора нафига?
Я уж не говорю о том, что это ограничение фактически обходится при помощи костылей как-то так, например:
class a {
int[] many_i;
void Main
{
if(..)
{
int i;
Calculate(i_index);
}
Console.ReadLine;
}
void Calculate(int i_index)
{
Thread thread = new Thread(delegate
{
Thread.Sleep(TimeSpan.FromSeconds(10;
many_i[i_index] = 5;
});
thread.Start;
}
Ну или на моем примере:
class Accumulators {
string[] many_s;
Accumulators {
many_s = new string[3];
button1.Click += accumulate_to(0);
button2.Click += accumulate_to(1);
button3.Click += accumulate_to(2);
button4.Click += new EventHandler(delegate(object sender, EventArgs e)
{
MessageBox.Show(string.format("s1: {0}, s2: {1}, s3: {2}", many_s[0], many_s[1], many_s[2];
});
}
EventHandler accumulate_to(int s_index) {
return new EventHandler(delegate(object sender, EventArgs e {
many_s[s_index] += "Yo!";
}
}
}
Только оба эти варианта получаются менее читаемыми, чем могли бы...
![](/images/graemlins/smile.gif)
его предложение тянет за собой, что .net должен следит за каждой value-переменной, а это за собой тянет ощутимые провалы по скорости работы.
> во-вторых, делать runtime exception
каким образом будет осуществляться эта проверка?
как твой пример будет работать, если метод Calculate находится уже в скомпилированном методе?
его предложение тянет за собой, что .net должен следит за каждой value-переменнойопять неверно
http://en.wikipedia.org/wiki/Escape_analysis
его предложение тянет за собой, что .net должен следит за каждой value-переменной,... на этапе компиляции. В runtime нужно следить только за некоторыми. И?
каким образом будет осуществляться эта проверка?Не потребуется, если сделать все правильно. Если же не следить за переменными - то наверняка есть такое понятие, как invalid reference или что-то такое?
Еще по обоим замечаниям: это же умеют делать в других языках, без больших потерь производительности. См. accumulator benchmark по ссылке в моих постах выше.
как твой пример будет работать, если метод Calculate находится уже в скомпилированном методе?Поясни вопрос?
ты забываешь о том, что метод Calculate может быть описан в другом модуле, который уже скомпилирован до byte-кода, и может быть даже уже запущен и скомпилирован до native-кода.
твой код с anonymous блоком подгружается может быть вообще динамически через несколько дней после запуска Calculate-метода.
или другими словами не надо забывать, что слова out/ref и так далее, это не слова языка, это слова виртуальной машины, соответственно язык (в данном случае C#) не может эти слова заменить на какое-то свое шаманское поведение.
ты забываешь о том, что метод Calculate может быть описан в другом модуле, который уже скомпилирован до byte-кода, и может быть даже уже запущен и скомпилирован до native-кода.и что?
в прототипе написано out, то есть VM заранее знает, за чем нужно особенно следить
Еще по обоим замечаниям: это же умеют делать в других языках, без больших потерь производительности. См. accumulator benchmark по ссылке в моих постах выше.То, что у тебя по ссылке - это совсем другая задача. Совсем не то, что ты хочешь сделать в своей программе. Аккумулятор делает замыкание, которое хранит переменную внутри себя. И увеличивает её. Внешние ссылки и объекты не модифицируются.
В гугле считают, что такого не бывает лишь по той причине, что не предусмотрен в текущем дотнете тип "reference to a reference".
Был бы этот тип - тогда было бы на порядок меньше проблем. Любой out параметр был бы reference, валидация жизни объектов, которая тебя так напрягает, была бы простой, как-то так:
1. dereference.
2. получили value-type? отлично, изменили.
3. получили reference-type? reference жив? отлично, изменили.
4. выкинули exception.
Еще раз напоминаю, вопрос был не в том "почему этого нету в C# 2.0", и не "почему это плохо, и этого не надо", а "будет ли/есть ли это в C# 3.0, и является ли его отсутсвие сейчас - ограничением дотнет платформы в целом". Флудеры, блин...
к языку C# это ограничение никакого отношения не имеет.
соответственно в C# 3.0 ничего не изменится, т.к. при выходе C# 3.0 никто VM менять не будет.
фактически он есть- это delegate
т.е. то, что ты хочешь записывается так:
class SomeForm
{
SomeForm
{
...
button1.Clicked += validate_bitmap_button(textPathTop, delegate(Bitmap bmp){bmpTop=bmp;});
button2.Clicked += validate_bitmap_button(textPathMiddle, delegate(Bitmap bmp){bmpMiddle=bmp;});
button3.Clicked += validate_bitmap_button(textPathBottom, delegate(Bitmap bmp){bmpBottom=bmp;});
...
}
EventHandler validate_bitmap_button(TextBox path, Execute<Bitmap> bmpRef)
{
return new EventHandler(delegate(object sender, EventArgs e)
{
try {
bmpRef(ValidateAndLoadBitmap(path.Text;
// Чтобы сделать validate, bitmap надо загрузить. Зачем потом грузить его еще раз?
} catch(FileIsInvalidForOurTask) {
//...
}
});
}
}
на C# 3.0
button1.Clicked += validate_bitmap_button(textPathTop, bmp => bmpTop=bmp;);
на верхнем уровне, вместо out/ref удобнее использовать делегаты, как в тех же самых ФЯ.
ref и out — это фактически возможность использовать & из C++, но в ограниченных ситуациях, когда это может привести к нарушению свойств managed code в .NET
Так в .NET есть возможность ссылаться на значения, которые находятся в стеке. По идее это позволяет, например, для рекурсивного алгоритма хранить в стеке список с какими-то данными от каждого вызова в последовательности вложенных вызовов. В Джава придется использовать кучу, что в некоторых случаях дает неприемлемую нагрузку на GC. В результате приходиться структуру кэшировать в объекте, что вызывает проблемы, когда этот объект используется множеством потоков, приходиться извращаться дальше.
Короче, ты и пытаетесь отмазаться что типа "такого не бывает", и вы не правы.Нет, никто не пытается отмазаться. Дарк хочет сказать о том, что невыгодно считать ссылки на value типы. Я хочу сказать, что твой пример по ссылке делает не то, что ты хочешь в топике.
Оставить комментарий
shlyumper
Гугление выдает чьи-то домыслы о том, что де так будет всегда, т.к. необходимые для реализации концепции не предусмотрены в managed code. Кто читал C# 3.0, там все так же печально?Ну и любопытство: F#/Nemerle этого обходить тоже не умеют?