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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Прерывание рекурсии через goto, Не является ли это нарушением чего-то? 
V
    Опции темы
Enteropoly
Дата 18.6.2009, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Вот допустим, есть такой код.
Код

private GTile FindTileByPoint(Point input, bool recursion)
        {            
            int xarray = (int)Math.Floor(input.X / (Globals.TileIntRadius * 2));
            int yarray = (int)Math.Floor(input.Y / (Globals.TileExtRadius * 1.5F));

            if ((yarray % 2 != 0) && !recursion)
            {
                FindTileByPoint(new Point(input.X - (int)Globals.TileIntRadius, input.Y), true);
                goto SRLB;
            }

            if (xarray < xsize && yarray < ysize)
            {
                if (xarray < 0)
                {
                    xarray = 0;
                }
                if (yarray < 0)
                {
                    yarray = 0;
                }
                return tiles[yarray, xarray];
            }

        SRLB: Globals.ServiceRecursionLoopBreaker(); 

            return null;
        }


Тут вся соль в том, что этот метод В ЛЮБОМ случае должен возвращать правильный ответ (tiles[yarray, xarray]), и никогда не возвращать null. Вот я пытаюсь предотвратить это путём джамперов. Вопрос чисто теоретический. Не является ли подобный способ нарушающим какие-то правила кодинга? 

Globals.ServiceRecursionLoopBreaker() - пустой метод.

Это сообщение отредактировал(а) Enteropoly - 18.6.2009, 13:34
PM MAIL   Вверх
PashaPash
Дата 18.6.2009, 14:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

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



Enteropoly, зачем тут вообще goto - там и else справится? и как работает магический метод ServiceRecursionLoopBreaker?


--------------------
PM MAIL WWW   Вверх
diadiavova
Дата 18.6.2009, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Enteropoly @  18.6.2009,  13:29 Найти цитируемый пост)
Globals.ServiceRecursionLoopBreaker() - пустой метод.

И зачем его вызывать? smile 
Я думаю, что ты гораздо быстрее получил бы помощь, если бы объяснил, что хочешь сделать.


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


Шустрый
*


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

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



В общем, суть такова. Данная функция ищет клетку на поле по положению мыши. Ессно, результат тут может быть единственный. Так как функция возвращает некий тип (эту самую клетку), то, соответственно, возвратить мы тут можем:

- верный ответ
- неверный ответ
- null

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

В данном случае я тупо прерываю на полпути работу функции (после того, как правильная клетка подсчитана) и через goto перехожу на "подставной" метод-пустышку, код которого:
Код

Globals.ServiceRecursionLoopBreaker()
{
}


Вот такие дела =))  smile 

ЗЫ. Всё это, конечно же, работает как часы =) Вопрос в том, считается ли это нормальным =)

ЗЗЫ. Сейчас я выхожу из функции простым ретурном:
Код

            int xarray = (int)Math.Floor(input.X / (Globals.TileIntRadius * 2));
            int yarray = (int)Math.Floor(input.Y / (Globals.TileExtRadius * 1.5F));
            if ((yarray % 2 != 0) && !recursion)
            {
                return FindTileByPoint(new Point(input.X - (int)Globals.TileIntRadius, input.Y), true);
                //goto SRLB;
            }

вопрос именно про goto.

Это сообщение отредактировал(а) Enteropoly - 18.6.2009, 16:31
PM MAIL   Вверх
diadiavova
Дата 18.6.2009, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Enteropoly @  18.6.2009,  16:27 Найти цитируемый пост)
В данном случае я тупо прерываю на полпути работу функции и через goto перехожу на "подставной" метод-пустышку

После чего всё это возвращается в вызвавший код, который продолжает выполняться, то есть функция всё равно возвращает null, а эффект от вызова пустышки тоже null.

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



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


Шустрый
*


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

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



diadiavova, я и вычисляю всё математически. Программа у меня вроде работает как положено, вопрос был чисто теоретический =)

Цитата

После чего всё это возвращается в вызвавший код, который продолжает выполняться, то есть функция всё равно возвращает null, а эффект от вызова пустышки тоже null.

Странно, у меня потом вроде ничё не возвращалось...


Из МСДН.
Цитата

goto (Справочник по C#)
Обновлен: Ноябрь 2007

Оператор goto передает управление именованному оператору.

Чаще всего оператор goto используется для передачи управления определенной подписи смены регистра или подписи по умолчанию в операторе switch.

Оператор goto также используется для выхода из вложенных циклов со сложной структурой.

PM MAIL   Вверх
diadiavova
Дата 18.6.2009, 17:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Для чего служит goto я в курсе. Я писал не о гоуту, а о вызове пустышки. После того как вызываемая функция отработает, управление снова передаётся к вызвавшей., то есть инструкция
Код

            return null;

всё равно выполнится. Поэтому смысла вызова пустышки вообще нет.
Что до теоретической части, то в твоём случае вместо гоуту надо писать  return null;. goto обычно используют для досрочного выхода из глубоких циклов.

Добавлено через 2 минуты и 13 секунд
Цитата(Enteropoly @  18.6.2009,  17:11 Найти цитируемый пост)
Странно, у меня потом вроде ничё не возвращалось...

null - это и есть "ничё"


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


Шустрый
*


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

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



Мы, кажется, немного о разных вещах вообще думаем =)
PM MAIL   Вверх
diadiavova
Дата 18.6.2009, 20:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Если я тебя не понял, то тут 2 варианта, либо у меня для этого слишком маленький моск, либо ты просто плохо объяснил. В первом случае я "умываю руки", во втором - попытайся сформулировать что тебе не понятно так чтобы я понял.


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


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

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



Enteropoly, если я правильно понял, то тебя интересует "законность" использования go to. в умных книжках пишут, что от использования этого оператора следует воздерживаться любыми способами, потому как он путает код(создает "спагетти код"), который сложно читать. так что с точки зрения "философии" то использование go to является нарушением. но с точки зрения реализации все ложится на плечи и совесть разработчика.
PM MAIL ICQ   Вверх
diadiavova
Дата 19.6.2009, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Экскалупатор,  smile 


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


Кот-программист
***


Профиль
Группа: Завсегдатай
Сообщений: 1206
Регистрация: 30.8.2005
Где: Спб

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



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


что тебе мешает вместо goto бла бла бла сразу написать return null ?

Кроме того я вообще не понимаю смысла твоего рекурсивного вызова. Смысл рекрсивного вызова в использовании возвращаемого значения. А у тебя после этого вызова оно не запомниается , а просто возвращается null.

По всей видимости у тебя все работает только потому что у тебя yarray всегда четное.

Кроме того постарайся не использовать рекурсию. Она усложняет читабельность и управляемость. Есть ряд задач , где ее применение оправдано , но это не та задача.

Добавлено через 1 минуту и 20 секунд
Да и насчет goto, Забудь это слово. Табу не просто так наложили. Если интересно более подробно , то поищи по форуму. Обсуждали не раз.


--------------------
Жизнь - печальная штука.
PM MAIL ICQ Skype GTalk   Вверх
Enteropoly
Дата 20.6.2009, 02:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

По всей видимости у тебя все работает только потому что у тебя yarray всегда четное


Ну в принципе, так и есть. Если оно нечётное, то я его делаю чётным и запускаю метод заново. Это происходит потому, что у меня таким образом ищутся шестиугольники, стоящие плотно друг к другу (а поиск идёт по двумерному массиву). Так как расположить их один под другим нельзя (тот, что ниже на половину сдвинут по отношению к верхнему), а поиск объекта на экране по координатам у меня достаточно простой, я делаю так:
- Ищу по координате Y на какой ряд клеток приходится найденный результат
- Если это нечётный ряд, то входная координата X сдвигается (т.к. и сам ряд как бы сдвинут)
- Теперь запускаем заново метод и находим клетку правильно

В результате, я попросту не могу вернуть null, иначе получится ерунда. И неправильный ответ я тоже вернуть не могу. А вернуть что-то необходимо. Вот и получается, что мне нужно как-то полюбому выбраться из метода до того, как он дойдёт до дефолтного return null. Я и делал через goto =)

Про goto теперь ясно. Спасибо всем, особенно Экскалупатору. 

PS. Про эту программу есть тема-побратим.

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

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


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

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


 




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


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

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