Я думаю, что это действительно хороший вопрос ...
В общем, я бы пошел с чем-то, что напоминает вариант 3 выше. В основном, подумайте о своем классе и о том, что он делает; есть ли у него какие-либо эффективные данные, кроме данных для анализа и проанализированных токенов? Если нет, то я бы сказал, что если у вас нет таких вещей, у вас нет экземпляра вашего класса; у вас есть неполный экземпляр вашего класса; то, что вы хотели бы избежать.
Одно из соображений, на которое вы указываете, заключается в том, что синтаксический анализ токенов может быть относительно сложным вычислительным процессом; это может занять некоторое время. Я согласен с вами, что вы, возможно, не захотите принять удар за это в конструкторе; в этом случае может иметь смысл использовать метод Parse (). Однако возникает вопрос, существуют ли какие-либо разумные операции, которые можно выполнить в вашем классе до завершения метода parse (). Если нет, то вы вернулись к исходной точке; перед завершением метода parse () вы фактически находитесь в состоянии «неполного экземпляра» вашего класса; это фактически бесполезно. Конечно, все меняется, если вы хотите и можете использовать многопоточность в своем приложении; если вы готовы перенести сложные вычислительные операции в другой поток и поддерживать некоторую синхронизацию в методах / средствах доступа вашего класса до тех пор, пока вы не закончите, тогда вся функция parse () имеет больше смысла, так как вы можете выбрать порождение что в новой ветке целиком. Тем не менее, вы по-прежнему сталкиваетесь с проблемами при попытке использовать ваш класс до того, как он полностью все проанализирует.
Я думаю, что в этот дизайн входит еще более широкий вопрос: какова большая область, в которой этот код будет использоваться? Для чего будет использоваться этот код, и этим, я имею в виду, не только сейчас, при предполагаемом использовании, но есть ли вероятность того, что этот код может расти или изменяться по мере того, как это делает ваше приложение? С точки зрения стабильности реализации , можете ли вы ожидать, что это будет полностью стабильно, или есть вероятность, что что-то из набора данных вы захотите проанализировать или размер данных для анализа или токены, в которые вы будете разбирать, изменится в будущем? Если реализация может измениться, рассмотрите все способы, которыми она может измениться; по моему опыту, эти соображения могут сильно привести к той или иной реализации. И рассмотрение этих вещей не тривиально; не длинным выстрелом.
Чтобы вы не думали, что это просто придирки, я бы сказал, по скромным подсчетам, примерно 10-15% написанных мною классов нуждались в некотором уровне рефакторинга еще до завершения проекта; редко есть дизайн, над которым я работал в выжившей реализации, чтобы выйти на другую сторону, выглядя так же, как и раньше. Таким образом, рассмотрение возможных изменений реализации становится очень полезным для определения того, какой должна быть ваша реализация. Если, скажем, ваша реализация никогда не захочет изменять размер строки для токенизации, вы можете сделать предположение о вычислительной сложности, которая может так или иначе привести вас к общему дизайну.