C# 有没有方法可以使方法防弹,例如,如果使用null参数调用该方法,那么它将给出异常?

C# 有没有方法可以使方法防弹,例如,如果使用null参数调用该方法,那么它将给出异常?,c#,C#,我有一个函数: public int GetIntSetting(SET setting, int nullState) { // Get the setting value or nullState if it was not set var str = GetStringSetting(setting, nullState.ToString()); // Check if it's an integer var

我有一个函数:

    public int GetIntSetting(SET setting, int nullState)
    {
        // Get the setting value or nullState if it was not set
        var str = GetStringSetting(setting, nullState.ToString());

        // Check if it's an integer
        var isInt = int.TryParse(GetStringSetting(setting, nullState.ToString()), out int parsed);

        // If integer then return else update settings and return nullState
        if (isInt )
        {
            return parsed;
        }
        else
        {
            UpdateIntSetting(setting, nullState);
            return nullState;
        }
    }

我想这样做,这样就不会有任何意外的机会从功能。如果您能给我一些建议,告诉我如何检查输入以及我应该考虑的其他方法,我将不胜感激。

这不是一个真正的
C#
问题。这是关于什么是函数以及它应该如何操作的基础知识。从技术上讲,“函数”应该将所有输入参数视为不可变的,并返回一些值。“方法”可能有副作用。这里您使用的是一个
C#
“方法”,但您可以将其视为一个函数,这往往会产生更干净的代码

编写函数时要记住的事项:

  • 无副作用
  • 将其简化为语义上有意义的最简单指令集
  • 尽可能减少分支和嵌套循环(这些通常是可以进行进一步重构以从当前函数中提取另一个函数的指标)
  • 用接口替换掉依赖项的具体类(这远远超出了我今天发布的内容的范围,但它有助于编写测试,并可以减轻维护过程中的麻烦)
  • 方法/功能应该做什么?试着用你的母语把它简化成几句话,然后试着把它们写成几行代码。看起来您的方法正在执行以下操作。。。“如果
    设置
    未设置为整数值,请将其设置为
    空值
    ,并返回其值。我希望最终的方法不会超过几行(我在这里故意说方法,因为有一个副作用-如果它“未设置”,则更改
    设置
    的值”)

    你可能最终会得到一个方法,但我将反复强调函数的重要性,并降低单个函数的复杂度,您可以显著降低所需的单元测试用例覆盖率。尽管如此,这也是您问题的核心,您仍然希望尝试识别方法/函数的所有边缘用例。例如,假设我有以下精心设计的函数

    bool IsPositive(int val) { return val > 0; }
    
    有明显的
    >0
    ,和
    <0
    ,以及边缘大小写
    ==0
    。当前,
    val=0
    将被视为负值,这可能是或可能不是所需的行为。此函数中只计算一个表达式,并且没有分支或循环,因此复杂度尽可能低,我们可以很容易地推断其行为


    特别是在C#方面。您可以将所有内容包装在一个通用的
    try/catch
    块中,但这就是…什么是“最佳实践”?哦,是的,垃圾。如果您认为您可能会遇到完全超出您控制的某种异常(即非托管资源-db连接、http客户端连接等)然后您可以专门针对该异常。然后您可以使用
    try/catch
    ,但只捕获该特定异常。这当然意味着您已经确定了函数中可能的故障点

    确定故障点的能力可以来自于理解您正在与之交互的数据结构,或者更常见的是,仅仅是经验(试错、调试)。这又一次超越了C#,回到了一般编程技能。与任何技能一样,它需要时间来培养,有些人天生就比其他人更擅长


    现在让我们看看你的代码

    public int GetIntSetting(SET setting, int nullState)
    
    什么是
    SET
    ?现在我们将忽略
    SET
    的行为可能封装在某个现有的.NET类中这一事实

    {
        // Get the setting value or nullState if it was not set
        var str = GetStringSetting(setting, nullState.ToString());
    
    您已检索到设置,或
    nullState.ToString()
    ,并将其保存在
    str
    中。因此,在下一行中,您可以使用它,而不是再次计算它。然而,这里您只使用了一次值,因此我认为为变量分配内存没有意义,只需在下一行中取消引用它即可

        // Check if it's an integer
        var isInt = int.TryParse(GetStringSetting(setting, nullState.ToString()), out int parsed);
    
    同样,没有理由将
    int.TryParse()
    结果保存到变量中,它可以移动到
    if
    表达式中。但是,您不需要
    TryParse
    ,因为如果未设置
    设置
    ,它将使用
    nullState.ToString()
    ,我们知道它必须是一个整数作为一个字符串,它将被成功解析。然后诀窍是找出
    GetStringSetting()
    实际做了什么(代码气味)

    局部地,您在
    if
    块中返回,不需要
    else

    因此,如果设置是一个整数值,则返回它,否则将其更改为
    nullState
    并返回
    nullState
    。但是我相信
    GetStringSetting()
    的第二个参数是返回的值,如果第一个参数是“未设置”,则不管这意味着什么(null?null还是空?)。这意味着,如果未设置设置(
    GetStringSetting(setting,nullState.ToString())
    ),您可能已经在使用
    nullState

    …但该设置可能已设置为非数字字符串(卷积边缘情况)。如果发生这种情况,该设置仍将是非数字字符串,但该方法的其余部分将使用
    nullState
    进行操作

    如果不了解更多其他代码,就很难说出您的边缘情况是什么,这往往是一种代码气味——需要其他代码了解方法/函数的行为(有时,在实践中,这是无法避免的)

    此方法具有潜在的副作用。如果未设置
    设置
    ,或不是整数值,则其值将更改为
    空状态
        // If integer then return else update settings and return nullState
        if (isInt )
        {
            return parsed;
        }
        else
        {
            UpdateIntSetting(setting, nullState);
            return nullState;
        }
    
    public int GetIntSetting(ISetting setting, int nullState)
    {
        int.Parse(GetStringSetting(setting, nullState.ToString()), out int parsed);
    
        if(parsed == nullState) 
        {
             UpdateIntSetting(setting, nullState);
        }
    
        return parsed;
    }
    
    public int GetIntSetting(ISetting setting, int nullState)
       => int.Parse(GetStringSetting(setting, nullState.ToString()), out int parsed);