Цепочка метода C# может быть “слишком длинной”?

Не с точки зрения удобочитаемости, естественно, так как можно всегда располагать отдельные методы в отдельные строки. Скорее действительно ли опасно, по какой-либо причине, объединить чрезмерно большое количество в цепочку методов вместе? Я использую метод, объединяющий в цепочку, прежде всего, для оставления свободного места при объявлении отдельных переменных с одним использованием и традиционно использовании методов возврата вместо методов, которые изменяют вызывающую сторону. За исключением строковых методов, они я вид цепочки беспощадно. В любом случае я иногда волную по поводу влияния использования исключительно длинных цепочек метода все в одной строке.

Скажем, я должен обновить значение одного объекта на основе чьего-то имени пользователя. К сожалению, самый короткий метод для получения корректного пользователя смотрит что-то как следующее.

SPWeb web = GetWorkflowWeb();
SPList list2 = web.Lists["Wars"];
SPListItem item2 = list2.GetItemById(3);
SPListItem item3 = item2.GetItemFromLookup("Armies", "Allied Army");
SPUser user2 = item2.GetSPUser("Commander");
SPUser user3 = user2.GetAssociate("Spouse");
string username2 = user3.Name;
item1["Contact"] = username2;

Все с 2 или 3 длится только один вызов, таким образом, я мог бы уплотнить его как следующее (который также позволяет мне избавиться от would-be-superfluous 1):

SPWeb web = GetWorkflowWeb();
item["Contact"] = web.Lists["Armies"]
                     .GetItemById(3)
                     .GetItemFromLookup("Armies", "Allied Army")
                     .GetSPUser("Commander")
                     .GetAssociate("Spouse")
                     .Name;

По общему признанию это выглядит намного длиннее, когда это - все в одной строке и когда Вы имеете int.Parse(ddlArmy.SelectedValue.CutBefore(";#", false)) вместо 3. Тем не менее, это - одна из средних длин этих цепочек, и я могу легко предвидеть некоторые исключительно более долгие количества. Исключая удобочитаемость, там что-нибудь, по поводу чего я должен быть взволнован для этих 10 + цепочки метода? Или нет ли никакой вред в использовании действительно действительно длинных цепочек метода?

22
задан Grace Note 17 May 2010 в 13:00
поделиться

4 ответа

Нет никаких технических ограничений на длину цепочки методов.

Однако три области, которые могут стать проблематичными: отладка , обработка исключений и удаление ресурсов .

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

Обработка исключений усложняется тем фактом, что вы не можете изолировать исключения, вызванные одним методом, от другого. Обычно это не проблема, если вы не можете сделать что-то значимое в ответ на исключение - просто позвольте ему распространиться вверх по цепочке вызовов.Однако, если позже вы поймете, что вам нужна обработка исключений, вам придется реорганизовать синтаксис цепочки, чтобы иметь возможность вставлять соответствующие обработчики try / catch.

Подобно обработке исключений, случай детерминированного удаления ресурсов. Самый простой способ в C # сделать это - использовать с помощью () - к сожалению, синтаксис цепочки этого не позволяет. Если вы вызываете методы, возвращающие одноразовые объекты, вероятно, было бы неплохо избежать синтаксиса цепочки, чтобы вы могли быть хорошим «гражданином кода» и избавляться от этих ресурсов как можно раньше.

Синтаксис цепочки методов часто используется в fluent API , где он позволяет синтаксису вашего кода более точно отражать последовательность операций, которые вы намереваетесь. LINQ - это один из примеров в .NET, где часто встречается плавный синтаксис / цепочка.

34
ответ дан 29 November 2019 в 04:12
поделиться

Это считается запах кода у одних, а у других - нет. Каждый раз, когда вы видите следующее:

Foo.getBar().getBlah().getItem().getName();

вы действительно должны думать: «Чего я на самом деле хочу?» Вместо этого, возможно, ваш метод должен содержать вызов функции:

String getName(Int _id, String _item)
{
    return myBar.getName( _id, _item );
}

, который затем делегирует вниз, среди классов. Затем, если что-то изменится в одном из ваших классов при более позднем обновлении, вы точно увидите, где это происходит, и сможете изменить это в одном месте.

6
ответ дан 29 November 2019 в 04:12
поделиться

Единственный вопрос, который вы должны рассмотреть по этому поводу (если вы игнорируете читабельность) - это обработка ресурсов и GC... Вам следует задать следующие вопросы.

  • Возвращают ли вызовы, которые я делаю, объекты, которые должны быть утилизированы?
  • Инициирую ли я много вещей в одной области видимости, а не в меньших областях, на которые GC может реагировать лучше? (GC планируется запускать каждый раз, когда вы покидаете область видимости, хотя планирование и то, когда он действительно запускается - две разные вещи :-p).

Но на самом деле... если вы вызываете по одному методу в строке или собираете их все вместе, то в IL все это будет выглядеть одинаково (или почти одинаково).

Josh

4
ответ дан 29 November 2019 в 04:12
поделиться

Читаемость - это самая большая проблема, но часто это вовсе не проблема.

Вы также можете описать синтаксис запроса LINQ как (под всем этим) точно такую ​​настройку.Это просто делает его красивее ;-p

Одна возможная проблема заключается в том, что вам нужно ввести такие вещи, как , используя или lock ; с плавным API у вас может возникнуть соблазн просто отбросить эти компоненты, но это может привести к странностям при возникновении исключения.

Другая возможная мысль состоит в том, что вам может потребоваться более детальная обработка исключений для некоторых вызовов; но вы всегда можете просто прервать поток:

var foo = bar.MethodA().MethodB(...).MethodC();
try {
    foo.MethodD();
} catch (SomeSpecificException) {
    //something interesting
}

Или вы даже можете сделать , что в методе расширения, чтобы сохранить плавный внешний вид:

bar.MethodA().MethodB(...).MethodC().MyExtensionMethodD();

где MyExtensionMethodD - это тот, который вы добавляете со специальной обработкой (исключения, блокировки, использование и т. д.).

7
ответ дан 29 November 2019 в 04:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: