c#重构两个几乎相同的方法

时间:2015-04-20 20:13:44

标签: c# refactoring

重构是好的,但有时候弄清楚如何重构并确实是否可以实际重构某些东西并不容易!

我有许多几乎相同的方法 - 我可以重构它们,但重构的一部分超出了我的逻辑。

以下是两种未重构的方法:

 private void projectToolStripMenuItem_Click(object sender, EventArgs e)
    {
        if (projectToolStripMenuItem.Checked)
        {
            projectToolStripMenuItem.Checked = false;
            if (!projectForm.IsDisposed) projectForm.Hide();
        }
        else
        {
            if (projectForm.IsDisposed)
                projectForm = new frmProject();
            projectForm.Show(dockPanel, DockState.DockRight);
            projectToolStripMenuItem.Checked = true;
        }

    }

    private void logginToolStripMenuItem_Click(object sender, EventArgs e)
    {
        if (logginToolStripMenuItem.Checked)
        {
            logginToolStripMenuItem.Checked = false;
            if (!outputForm.IsDisposed) outputForm.Hide();
        }
        else
        {
            if (outputForm.IsDisposed)
                outputForm = new frmOutput();
            outputForm.Show(dockPanel, DockState.DockBottom);
            logginToolStripMenuItem.Checked = true;
        }
    }

使用Refactoring,我会得到一个这样的方法,以前未重构的方法会调用

private void refactoredMethod(TooStripMenuItem menuItem, DockContent frmName)
{

        if (menuItem.Checked)
        {
            menuItem.Checked = false;
            if (!frmName.IsDisposed) frmName.Hide();
        }
        else
        {
            if (frmName.IsDisposed)
                frmName= new frmProject(); // Still Problematic
            frmName.Show(dockPanel, DockState.DockRight);
            menuItem.Checked = true;
        }
    }

那么我们有一个几乎完全重构的方法 - 有一个问题,如何判断哪个form我希望从frmName变量中实例化?

3 个答案:

答案 0 :(得分:8)

您可以使该方法具有通用性,并利用new()通用约束。

private TForm refactoredMethod<TForm>(TooStripMenuItem menuItem, TForm frmName) where TForm : Form, new()
{
    if (menuItem.Checked)
    {
        menuItem.Checked = false;
        if (!frmName.IsDisposed) frmName.Hide();
    }
    else
    {
        if (frmName.IsDisposed)
            frmName= new TForm();
        frmName.Show(dockPanel, DockState.DockRight);
        menuItem.Checked = true;
    }
    return frmName;
}

所以你可以称之为

projectForm = refactoredMethod<frmProject>(projectToolStripMenuItem, projectForm);

一个限制是您的表单应该具有公共无参数构造函数。如果您有Form参数化构造函数,则可以将Func<TForm>传递给充当工厂方法的方法。

答案 1 :(得分:1)

将工厂传递给方法,如下所示:

private void RefactoredMethod(..., Func<TypeOfItemToCreate> creator)
{
    ...
    if (frmName.IsDisposed)
            frmName = creator(); 
}

唯一的要求是您创建的两个类都需要具有一些通用接口或基类。

答案 2 :(得分:1)

我看到已经有答案但还想写更多内容。我相信重构比你在这里描述的要多得多。 一个是改变函数的名称,一个是将代码放入单独的函数中。 还记得没有适当的单元测试就没有适当的重构。

在您的示例中,您将高级功能与低级功能混合使用 (将false改为true,创建对象等),函数本身也不是自我描述的。

因此,在重构方面还有很多工作要做:

void hideForm(TForm form){
    if(!form.IsDisposed){
        form.Hide();
    }
}

void showFormInDockPanel<TForm>(TForm form, DockPanel dockPanel){
    if(form.IsDisposed){
        form = new TForm();
    }
    form.Show(dockPanel, DockState.DockRight);
}

void toggleFormAndMenuItem<TForm>(TForm form, TooStripMenuItem menuItem){
    if(menuItem.checked){
        hideForm(form);
    }
    else {
        showFormInDockPanel<TForm>(form, dockPanel);
    }

    menuItem.checked = !menuItem.checked;
}

private void projectToolStripMenuItem_Click(object sender, EventArgs e){
    toggleFormAndMenuItem<frmProject>(projectToolStripMenuItem, projectForm);
}