对方法重载感到困惑

时间:2010-11-08 10:59:03

标签: c# optional-parameters

我正在使用.NET 4.0和ASP.NET 4.0以及C#(那是C#4.0吗?)。

我想将一些数据插入到我的SQL Server数据库中,我有一个这样的方法来处理这个:

public int InsertTrade(
    string symbol,
    string tradeSetupId,
    int tradeTypeId,
    decimal lotsPerUnit,
    string chartTimeFrame,
    int tradeGrade,
    int executionGrade,
    int MFEPips,
    int MAEPips,
    decimal pctAccountRisked
    )
{
    SqlCommand cmd = new SqlCommand("usp_InsertTrade");
    cmd.Parameters.AddWithValue("@symbol", symbol);
    cmd.Parameters.AddWithValue("@pctAccountRisked", pctAccountRisked);
    cmd.Parameters.AddWithValue("@tradeSetupId", tradeSetupId);
    cmd.Parameters.AddWithValue("@lotsPerUnit", lotsPerUnit);
    cmd.Parameters.AddWithValue("@tfCode", chartTimeFrame);
    cmd.Parameters.AddWithValue("@MAEPips", MAEPips);
    cmd.Parameters.AddWithValue("@MFEPips", MFEPips);
    cmd.Parameters.AddWithValue("@tradeGrade", tradeGrade);
    cmd.Parameters.AddWithValue("@executionGrade", executionGrade);
    return (InsertData(cmd, "trade"));
}

有几个非必填字段:tradeGrade,executionGrade,MFEPips,MAEPips。 usp_InsertTrade存储过程将这些可选参数公开为NULLable。在C#中编写代码的最佳方法是什么?我正在学习编程,所以如果你能提供有关最佳实践的指导,那就太棒了。

以下是usp_InsertTrade的存储过程参数:

CREATE procedure [dbo].[usp_InsertTrade]
@symbol char(6),
@tradeSetupId varchar(10),
@tradeTypeId int,
@lotsPerUnit decimal(18,1),
@chartTimeFrame varchar(5),
@tradeGrade smallint = NULL,
@executionGrade smallint = NULL,
@MFEPips int = NULL,
@MAEPips int = NULL,
@pctAccountRisked decimal(3,2)
AS

非常感谢。

更新

我已经更改了我的功能,以便可选参数位于底部。像这样:

public int InsertTrade(
    string symbol,
    string tradeSetupId,
    int tradeTypeId,
    decimal lotsPerUnit,
    string chartTimeFrame,
    decimal pctAccountRisked,
    int? tradeGrade,
    int? executionGrade,
    int? MFEPips,
    int? MAEPips
    )
{
    SqlCommand cmd = new SqlCommand("usp_InsertTrade");
    // required parameters
    cmd.Parameters.AddWithValue("@symbol", symbol);
    cmd.Parameters.AddWithValue("@tradeSetupId", tradeSetupId);
    cmd.Parameters.AddWithValue("@tradeTypeId", tradeTypeId);
    cmd.Parameters.AddWithValue("@lotsPerUnit", lotsPerUnit);
    cmd.Parameters.AddWithValue("@tfCode", chartTimeFrame);
    cmd.Parameters.AddWithValue("@pctAccountRisked", pctAccountRisked);

    // optional parameters
    if (MAEPips.HasValue)
        cmd.Parameters.AddWithValue("@MAEPips", MAEPips);
    if (MFEPips.HasValue)
        cmd.Parameters.AddWithValue("@MFEPips", MFEPips);
    if (tradeGrade.HasValue)
        cmd.Parameters.AddWithValue("@tradeGrade", tradeGrade);
    if (executionGrade.HasValue)
        cmd.Parameters.AddWithValue("@executionGrade", executionGrade);
    return (InsertData(cmd, "trade"));
}

当我使用此代码调用该函数时:

DBUtil DB = new DBUtil();
int tradeId = DB.InsertTrade (
    ddlSymbols.SelectedValue,
    ddlTradeSetups.SelectedValue, 
    ddlTradeTypes.SelectedValue, 
    decimal.Parse(txtLotsPerUnit.Text),
    ddlTimeFrames.Text,
    decimal.Parse(txtAcctRisk.Text));

我收到此错误:

No overload for method 'InsertTrade' takes 6 arguments

7 个答案:

答案 0 :(得分:5)

使用C#4.0,您可以将optional parametersnullable types结合使用:

public int InsertTrade(
    string symbol,
    string tradeSetupId,
    int tradeTypeId,
    decimal lotsPerUnit,
    string chartTimeFrame,
    decimal pctAccountRisked,
    int? tradeGrade = null,
    int? executionGrade = null,
    int? MFEPips = null,
    int? MAEPips = null
    )
{
    SqlCommand cmd = new SqlCommand("usp_InsertTrade");
    cmd.Parameters.AddWithValue("@symbol", symbol);
    cmd.Parameters.AddWithValue("@pctAccountRisked", pctAccountRisked);
    cmd.Parameters.AddWithValue("@tradeSetupId", tradeSetupId);
    cmd.Parameters.AddWithValue("@lotsPerUnit", lotsPerUnit);
    cmd.Parameters.AddWithValue("@tfCode", chartTimeFrame);
    if(MAEPips.HasValue)
        cmd.Parameters.AddWithValue("@MAEPips", MAEPips);
    if(MFEPips.HasValue)
        cmd.Parameters.AddWithValue("@MFEPips", MFEPips);
    if(tradeGrade.HasValue)
        cmd.Parameters.AddWithValue("@tradeGrade", tradeGrade);
    if(executionGrade.HasValue)
        cmd.Parameters.AddWithValue("@executionGrade", executionGrade);
    return (InsertData(cmd, "trade"));
}

使用这么多参数,您可能需要考虑introduce parameter object重构 - 它将使您的代码在将来更易于阅读和修改。

答案 1 :(得分:3)

我会创建一个struct来封装参数。

以下是我可能想到的可行方法:

  1. 可选参数。您可以使用一些可选参数定义方法,使用C#4.0语法(此功能已存在于VB中,但最近已添加到C#中)。缺点:您受限于如何使用可选参数。只有最后一个参数可以选择。我的意思是,如果您(名称,地址,电话)作为参数,按此顺序,您不能跳过地址和设置名称
  2. 结构。如上所述,这是我最喜欢的方式。您可以设置任何空值,但必须为每个方法创建一个结构
  3. 定义重载:最糟糕的技术是为每个组合的参数定义一个重载,这对于大型参数集合是不可行的
  4. 对象数组:仅当所有参数具有不同类型时才可行。您可以根据对象数组中每个条目的类型确定参数
  5. Dictionary<string,object>:另一种有趣的方法。每个条目都使用密钥映射
  6. 希望得到帮助

答案 2 :(得分:1)

我会创建一个扩展方法来摆脱对可空变量的重复检查。扩展方法类似于:

public static class SqlCommandExtensions
{
    public static void AddNullableInParameter<T>(this SqlCommand command, string columnName, Nullable<T> value) where T : struct
    {
        if (value.HasValue)
        {
            command.Parameters.AddWithValue(columnName, value.Value);
        }
    }
}

现在你可以写command.AddNullableInParameter("@yourParameter", YourNullableType);而不是所有if语句。

答案 3 :(得分:0)

您可以在参数中使用可为空的值,并在添加参数之前检查值,这样如果未提供该值,它将使用存储过程的默认值:

public int InsertTrade(
    ...
    int? executionGrade,
    ...
    )
{
    SqlCommand cmd = new SqlCommand("usp_InsertTrade");
    ...
    if(executionGrade.HasValue)
        cmd.Parameters.AddWithValue("@executionGrade", executionGrade);
    return (InsertData(cmd, "trade"));
}

答案 4 :(得分:0)

请参阅有关可空类型的链接:http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx

简而言之,将您的功能声明为:

public int InsertTrade(
    string symbol,
    string tradeSetupId,
    int tradeTypeId,
    decimal lotsPerUnit,
    string chartTimeFrame,
    int? tradeGrade,
    int? executionGrade,
    int? MFEPips,
    int? MAEPips,
    decimal pctAccountRisked
    )

答案 5 :(得分:0)

另一种方法可能是使用optional parameters

答案 6 :(得分:0)

听起来您正在使用Visual Studio 2010,C#4.0,因此他们现在引入了可选参数:http://msdn.microsoft.com/en-us/library/dd264739.aspx