Ответ 1
Чтобы сделать это правильно, вам нужен глобальный граф вызовов над приложением С#, рассчитанный с использованием семантики С#, а также суммарный анализ, включающий библиотеки, которые он вызывает. С таким графиком вызовов вы можете перечислять циклы в нем, и это будут кандидаты для проверки.
Я не знаю, где вы могли бы получить инструмент, который вычисляет такой глобальный граф вызовов для С# с полки.
Вы можете приблизиться к этому, используя простые методы сканирования кода. Для каждого метода M выберем набор вызовов apparant, который он содержит как идентификаторы I. В основном они будут отображаться как синтаксис, который выглядит как идентификатор (. После этого шага у вас есть M_i → I. Вы можете построить это как (экзистенциально консервативный) базовый график вызовов, а затем вычислить транзитивное замыкание. При этом у вас есть приблизительный график вызовов с циклами, и вы можете выполнять анализ цикла. Это массовые методы передавались по именам и другим случаям, но это может быть достаточно хорошо.