Types c#4.0-重构块的最佳方法;如果(某物是类型){}";声明?

Types c#4.0-重构块的最佳方法;如果(某物是类型){}";声明?,types,c#-4.0,refactoring,Types,C# 4.0,Refactoring,我有一些代码看起来像这样 public void ResetControls(Control controlOnPage) { if (controlOnPage is TextBox) { ResetTextBoxControl(controlOnPage); } if (controlOnPage is MediaPicker) { ((MediaPicker)controlOnPage).Media = null;

我有一些代码看起来像这样

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警告我“不要对这段代码进行不必要的强制转换”,但我不确定如何重写它以使其更好。有什么想法吗?

为了避免重复的演员阵容,您可以将其转换为:

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

MediaPicker mediaPickerControl = controlOnPage as MediaPicker;
if (mediaPickerControl != null)
{
    mediaPickerControl.Media = null;
}
重复你的其他演员


您还可以将其与一些嵌套的案例相结合,这样,如果您知道它已经是其他内容(例如文本框),您就不必尝试执行强制转换。最明显的做法是在
if
前面插入一个
else

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
。我也会对它们进行排序,以便更多的常见情况出现在不常见情况之前。

我认为FXCop不喜欢代码,因为一个很好的面向对象解决方案是将虚拟方法
ResetControl
添加到
控件
类中(当然,您不能这样做)

如果您想要一个清晰的面向对象解决方案,您可以创建一个接口
IResetableControl
,并为实现该接口的每个控件创建一个派生类

如果您只是想使现有代码在语法上更好,可以使用以下帮助器方法:

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

这与您的原始代码具有完全相同的语义,但有点更好(我认为FxCop会接受它)。请注意,泛型类型参数是从lambda表达式中指定的类型推断出来的,例如
(TextBox t)
。这还消除了在处理案例的代码内部执行额外强制转换的需要,因为您已经获得了正确类型的值(例如,
mp
)。

这将破坏“if control is SomeType”语句的(imho)可读链,并在
if
之前隐藏强制转换中的类型问题。我不会说这是一种改进。@Johannes它确实消除了重复的强制转换。但是牺牲可读性来改进(可疑的)性能并不总是正确的。我想这也可以被编译器消除。@Johannes:我不认为这是被编译器消除的,但我同意,以你现在的方式编写它对读者来说更清晰。它将比Rowland的代码稍微慢一点,但这可能无关紧要。然而,罗兰的回答也将消除FXCop错误,因为这样你就可以施放一次而不是两次。@Johannes FXCop警告告诉你它还没有被编译器消除。正如我在我的帖子中提到的,总是有可能在某些条件逻辑中将这些链接起来。当然,可读性也是主观的。。。
IfCast(controlOnPage, (TextBox t) =>
    ResetTextBoxControl(t));

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