C# 我应该使用异常来处理用户输入验证吗?

C# 我应该使用异常来处理用户输入验证吗?,c#,asp.net-mvc,asp.net-mvc-4,C#,Asp.net Mvc,Asp.net Mvc 4,我正在将业务逻辑代码从控制器移动到业务类。我的页面需要大量的用户输入验证。这在我的代码中创建了许多嵌套级别。因此,我在业务层中重新编写了如下代码: public RmaDetail SerialNumberScan(int rmaNumber, int serialNumber, RepairInvoice repairInvoice) { var result = SelectRmaDetail(rmaNumber, serialNumber); if (result

我正在将业务逻辑代码从控制器移动到业务类。我的页面需要大量的用户输入验证。这在我的代码中创建了许多嵌套级别。因此,我在业务层中重新编写了如下代码:

    public RmaDetail SerialNumberScan(int rmaNumber, int serialNumber, RepairInvoice repairInvoice) {
    var result = SelectRmaDetail(rmaNumber, serialNumber);

    if (result != null) throw new BusinessException("Serial Number not found.");

    if (result.Received != 1) throw new BusinessException("Line item has not been received.");

    bool? workOrderClosed = WorkOrderClosed(result.LNSEQNBR, result.LNSEQNBR, serialNumber);

    if (!workOrderClosed.HasValue) throw new BusinessException("Work order not found.");

    if (workOrderClosed.Value == false) throw new BusinessException("Work order not closed.");

    repairInvoice.TerminalType = result.ITEMNMBR.Trim();
    repairInvoice.UnderWarranty = RepairInvoiceDataLayer.UnderWarranty(result.RETDOCID, result.LNSEQNBR, serialNumber, result.CUSTNMBR);

    return result;
}
这是我的控制器:

    public ActionResult SerialNumberScan(string rmaNumber, string serialNumber)
{
    if (ModelState.IsValid)
    {
        ModelState["SerialNumber"].Value = new ValueProviderResult(serialNumber, serialNumber, CultureInfo.CurrentCulture);
        try
        {
            var rmaDetail = BusinessLayer.SerialNumberScan(rmaNumber, serialNumber, repairInvoice);
            Session["RmaDetail"] = rmaDetail;
            ViewBag.SetFocusTo = "#RepairLevels";
        }
        catch (BusinessException ex)
        {
            ViewBag.AlertMessage = ex.Message;
        }
    }

    return View("Index", repairInvoice);
}

line ViewBag.AlertMessage是一条显示在我的页面顶部的消息。我喜欢这种方法,因为它可读性很强。然而,我知道例外情况非常昂贵。有更好的方法吗

只有当您将异常作为正常程序流的一部分抛出时,异常才会变得昂贵。一般来说,异常应该用于处理异常情况,所以您的用例肯定是合格的:缺少序列号或行项目的情况确实是异常的

不过,我要更改的一件事是使用相同的异常,即BusinessException来处理所有验证。一方面,这使您的代码非常简单,因为您总是抛出相同的异常-唯一不同的是消息。另一方面,它剥夺了你以不同方式处理各种情况的灵活性


我认为,将子案例引入BusinessException将导致更好的方法。添加新的异常-在本例中,MissingSerialNumber和MissingLineItem异常使它们成为BusinessException的子类,以便您可以根据需要一起处理它们,并且在抛出这些异常的点上不使用参数构造函数。

只有在将异常作为正常程序流的一部分抛出时,异常才会变得昂贵。一般来说,异常应该用于处理异常情况,所以您的用例肯定是合格的:缺少序列号或行项目的情况确实是异常的

不过,我要更改的一件事是使用相同的异常,即BusinessException来处理所有验证。一方面,这使您的代码非常简单,因为您总是抛出相同的异常-唯一不同的是消息。另一方面,它剥夺了你以不同方式处理各种情况的灵活性


我认为,将子案例引入BusinessException将导致更好的方法。添加新异常-在本例中,MissingSerialNumber和MissingLineItem异常将它们作为BusinessException的子类,以便您可以根据需要一起处理它们,并且在引发这些异常的点上不使用参数构造函数。

首先,只有在引发异常时,异常才会很昂贵。如果有问题,应该扔掉它们。就性能而言,我认为在这种情况下,您不应该担心它,我们这里说的不是秒,而是毫秒。用户肯定不会注意到抛出异常并告诉他们的代价

此外,您还可以编写如下扩展方法:

    public static void Throw<T>(this bool expression, string alert) where T : Exception
    {
        if (!expression)
            throw (T)Activator.CreateInstance(typeof(T), alert);
    }
然后,您可以将所有这些if/throw检查替换为:

(result.Received != 1).Throw<BusinessException>("message");

首先,异常只有在抛出时才会代价高昂。如果有问题,应该扔掉它们。就性能而言,我认为在这种情况下,您不应该担心它,我们这里说的不是秒,而是毫秒。用户肯定不会注意到抛出异常并告诉他们的代价

此外,您还可以编写如下扩展方法:

    public static void Throw<T>(this bool expression, string alert) where T : Exception
    {
        if (!expression)
            throw (T)Activator.CreateInstance(typeof(T), alert);
    }
然后,您可以将所有这些if/throw检查替换为:

(result.Received != 1).Throw<BusinessException>("message");

这个问题似乎是离题的,因为它是关于在CODReVIEW.SE上发布的一个方法的一般代码审查,而不是一个关于它的特定问题的问题。抛出异常,然后处理它,我会说是非常昂贵的。而是创建一个具有错误/成功代码、消息和数据对象作为属性的泛型类。。用适当的错误和消息填充对象。内部视图检查操作是否成功,如果没有显示错误消息。@学习代码可以提供一个代码示例吗?这个问题似乎是偏离主题的,因为它是关于一个考虑在CoDeEvIEW.SE上发布的方法的一般代码审查的问题。而不是关于它的特定问题的问题。抛出异常然后处理它,我认为这是非常昂贵的。。而是创建一个具有错误/成功代码、消息和数据对象作为属性的泛型类。。用适当的错误和消息填充对象。内部视图如果没有显示错误消息,请检查操作是否成功。@LearningByCoding能否提供一个代码示例?