方法重载或更优雅的东西?

时间:2016-06-08 17:24:27

标签: c# overloading named-parameters

我正在用C#编写一些代码,我注意到下面的情况。我想知道如何才能让它更优雅,更易于维护。

如果我有以下带有重载的方案

public void DoSmtg(string a) { DoSmtg(a, 0, 0f); }
public void DoSmtg(string a, int x) { DoSmtg(a, x, 0f); } 
public void DoSmtg(string a, int x, double d) { // method logic }

现在说我需要添加另一个bool参数。我必须将其修改为

public void DoSmtg(string a) { DoSmtg(a, 0, 0f, false); }
public void DoSmtg(string a, int x) { DoSmtg(a, x, 0f, false); } 
public void DoSmtg(string a, int x, double d, bool doIt) { // method logic }

这是一个非常简单的例子。可以说有10个版本的DoSmtg()方法。显然,这段代码闻起来。虽然重载非常有效,但显然很难维护此代码,因为:

  1. 有很多方法可以写

  2. 在仔细调查之前调用哪种方法并不明显(特别是如果方法有更多参数)

  3. 通过增长参数列表

  4. 来获取方法
  5. 添加的新参数需要在很多地方进行更改(考虑从多个不同位置调用的上述方法)

  6. 避免这样的事情会是一种优雅,简单和好的方法吗?

3 个答案:

答案 0 :(得分:3)

您可以尝试在一个函数上添加所有参数,使用默认值并在调用函数时命名参数:

public void DoSmtg(string a, int x=0, double d=0f, bool doIt=false) { 
    // method logic 
}

调用该函数时,您将执行以下操作:

DoSmtg("yo!")
DoSmtg("yo!", d:0.59, doIt:true)

答案 1 :(得分:3)

您可以将所有参数包装在POCO中:

var parameters = new SomethingParameters()
{
    A = "foobar",
    X = 123,
    D = 0.123,
    DoIt = false
}

DoSmtg(parameters);

然后方法签名变为:

public void DoSmtg(string a, int x, double d, bool doIt)
    => DoSmtg(new SomethingParameters()
              {
                  A = a,
                  X = x,
                  D = d,
                  DoIt = doIt
              });

我喜欢这种模式,因为将来很容易扩展。如果你需要再添加五个参数或可选参数,没问题!

你可以这样称呼:

private void createTablesForBuilding() {
    int buildingcoutns = 5;

    for (int i = 0; i < buildingcoutns; i++) {
        myTables tbls = new myTables();
        tbls.setTableID(i);

        tables.add(tbls);

        JTable thistable = tables.get(i).table;

        thistable.setModel(new javax.swing.table.DefaultTableModel(
                new Object[][]{
                    {null, null, null, null},
                    {null, null, null, null},
                    {null, null, null, null},
                    {null, null, null, null}
                },
                new String[]{
                    "Title 1", "Title 2", "Title 3", "Title 4"
                }
        ));

        tables.get(i).table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (thistable.getSelectedRow() > -1) {
                    System.out.println("tableID is:"+tbls.getTableID());
                }
            }
        });

        Buildings_Panel.add(tables.get(i));
    }
}

如果你有很多代码调用你不想破坏的旧方法签名,你可以保留现有的重载,但让他们调用新的重载:

public class myTables extends javax.swing.JPanel {

int tableID = 0;

public myTables() {
    initComponents();
}

public void setTableID(int i){
    tableID = i;
}
public int getTableID(){
    return tableID;
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    jScrollPane1 = new javax.swing.JScrollPane();
    table = new javax.swing.JTable();

    setLayout(new java.awt.CardLayout());

    table.setModel(new javax.swing.table.DefaultTableModel(
        new Object [][] {
            {null, null, null, null},
            {null, null, null, null},
            {null, null, null, null},
            {null, null, null, null}
        },
        new String [] {
            "Title 1", "Title 2", "Title 3", "Title 4"
        }
    ));
    jScrollPane1.setViewportView(table);

    add(jScrollPane1, "card2");
}// </editor-fold>                        


// Variables declaration - do not modify                     
private javax.swing.JScrollPane jScrollPane1;
public javax.swing.JTable table;
// End of variables declaration                   

答案 2 :(得分:2)

我更喜欢为参数使用单独的类。但也许,正如你所说,你已经在多个地方调用了该方法,并且不想修改它。
在这种情况下,您可以添加一个可选参数:

public void DoSmtg(string a, int x, double d, bool doIt = false) 

除了您可以选择提供参数外,其他任何地方都不得更改。

如果你发现自己这样做了,我仍然会使用类来编写额外的重载并开始使用它。如果它们太多,可选参数也会开始变得混乱。