c # 4.0 - лучший способ реорганизовать блок операторов If (что-то типа) {}? - PullRequest
1 голос
/ 06 мая 2010

У меня есть какой-то код, похожий на этот,

public void ResetControls(Control controlOnPage)
{
    if (controlOnPage is TextBox)
    {
        ResetTextBoxControl(controlOnPage);
    }

    if (controlOnPage is MediaPicker)
    {
        ((MediaPicker)controlOnPage).Media = null;
    }

    if (controlOnPage is RelatedContentPicker)
    {
        ((RelatedContentPicker)controlOnPage).RelatedContentCollection = null;
    }
    ...
    ...

    foreach (Control child in controlOnPage.Controls)
    {
        ResetControls(child);
    }
}

Идея заключается в том, что я могу передать страницу методу, и он будет рекурсивно сбрасывать все элементы управления на его состояния по умолчанию - в случае MediaPicker и RelatedContentPicker, это пользовательские элементы управления, которые я создал .

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

Ответы [ 3 ]

2 голосов
/ 06 мая 2010

Я думаю, что FXCop не нравится код, потому что хорошим объектно-ориентированным решением было бы добавить виртуальный метод ResetControl к классу Control (что вы, конечно, не можете сделать).

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

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

public void IfCast<T>(object obj, Action<T> f) {
  if (obj is T) f((T)obj);
}

Тогда вы могли бы просто написать:

IfCast(controlOnPage, (TextBox t) =>
    ResetTextBoxControl(t));

IfCast(controlOnPage, (MediaPicker mp) => {
    mp.Media = null; });

Это имеет ту же семантику, что и ваш исходный код, но это немного приятнее (и я думаю, что FxCop примет это). Обратите внимание, что параметр универсального типа выводится из типа, указанного в лямбда-выражении, например, (TextBox t). Это также избавляет от необходимости выполнять дополнительное приведение в коде, который обрабатывает регистр, потому что вы уже получаете значение правильного типа (например, mp).

1 голос
/ 06 мая 2010

Самое очевидное, что нужно сделать, это добавить else перед if s:

if (controlOnPage is TextBox)
{
    ResetTextBoxControl(controlOnPage);
}

else if (controlOnPage is MediaPicker)
{
    ((MediaPicker)controlOnPage).Media = null;
}

else if (controlOnPage is RelatedContentPicker)
{
    ((RelatedContentPicker)controlOnPage).RelatedContentCollection = null;
}

Нет необходимости пытаться привести к MediaPicker или RelatedContentPicker, если элемент управления равен TextBox. Я бы также распорядился, чтобы более распространенные случаи предшествовали менее распространенным.

0 голосов
/ 06 мая 2010

Чтобы избежать дублирования приведения, вы можете преобразовать это:

if (controlOnPage is MediaPicker)
{
    ((MediaPicker)controlOnPage).Media = null;
}

будет:

MediaPicker mediaPickerControl = controlOnPage as MediaPicker;
if (mediaPickerControl != null)
{
    mediaPickerControl.Media = null;
}

Повторите для остальных бросков.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...