C# 参数是否可选,取决于以前的参数

C# 参数是否可选,取决于以前的参数,c#,.net,C#,.net,我有两种方法: Foo(int a, bool useDb) Foo(int a, bool useDb, DbContext dbContext) 有没有一种方法可以将其作为一种方法,使用这些规则? 如果useDb为真,则dbContext是必需的 如果useDb为false,则dbContext是可选的 编辑: 只是为了澄清一下,我想做的是: 在业务/服务层,我有ItemService方法GetItemStatus。它连接到数据库,获取数据并计算状态 没什么特别的。它创建了一个DbCont

我有两种方法:

Foo(int a, bool useDb)
Foo(int a, bool useDb, DbContext dbContext)
有没有一种方法可以将其作为一种方法,使用这些规则?
如果
useDb
为真,则
dbContext
是必需的
如果
useDb
为false,则
dbContext
是可选的

编辑:

只是为了澄清一下,我想做的是: 在业务/服务层,我有
ItemService
方法
GetItemStatus
。它连接到数据库,获取数据并计算状态

没什么特别的。它创建了一个DbContext(EF6.0),执行该操作并将其释放。标准但是,如果我想将GetItemStatus用作不同事务的一部分,该怎么办?哈我需要将DbContext传递到内部,并且不要明显地处理它。我创造了这样的东西:

    public ItemStatus GetItemStatus(int itemId, OfficeContext fni = null)
    {
        bool shouldBeDisposed = (fni == null) ? true : false;
        if (shouldBeDisposed) fni = ContextFactory.CreateOfficeContext();

        try
        {

            Do the stuff...

        }
        finally
        {
            if (shouldBeDisposed) fni?.Dispose();
        }

        return ...
    }
但现在我有点害怕,因为如果有人打电话:

GetItemStatus(123456)

。。。他忘了添加DbContext。我不确定他是不是真的这么想。虽然不应该那么糟糕。他将创建一个新的并处理它


但我在想最好的办法,以确保开发者不会犯错误。“万无一失”的方法。

听起来这只是你如何做的问题

这将是一个解决方案:

Public void Foo(int a, bool useDB, DbContext dbContext)
{
   if(useDb)
   {
       //use the database
   }
   else
   {
      //do whatever you would otherwise do.
   }
}
然后,在调用该方法时,有两个选项:

Foo(1, true, db); //calls Foo with useDB and a dbContext

Foo(1, false, null); //calls Foo with useDB false and null dbContext

在C#中,无法让单个函数签名实现这一点。您可以实现的最接近的方法是使用重载

public Foo(int a) { Foo(a, false, null); }
public Foo(int a, DbContext dbContext){ Foo(a, true, dbContext); }
private Foo(int a, bool useDb, DbContext dbContext){ ... }

包含所有参数的重载可以是私有的,因此不会使用无效参数调用它。

无法强制执行情景可选参数

您仍然可以将其设置为可选参数,然后在未提供所需参数的情况下手动引发异常

public void Foo(int a, bool useDB, DbContext dbContext = null)
{
    if(useDB && dbContext == null)
    {
        throw new Exception("DB context must be supplied!");
    }

    //...
}
但是,这将在运行时导致异常,并且不会在编译时警告您。您将不得不修复之前省略的db上下文,这不是首选方法


我想知道对
useDB
boolean的需求是什么。您已经可以从是否传递了上下文中得出:

public void Foo(int a, DbContext dbContext)
{
    //you already know useDB == true
}

public void Foo(int a)
{
    //you already know useDB == false
}
通过将dbcontext设置为可选参数,也可以将其放入单个方法中:

public void Foo(int a, DbContext dbContext = null)
{
    bool useDB = (dbContext != null);
}
这似乎是一个更干净的方法。您省略了一个冗余参数(
useDB
),这反过来又不需要强制执行一个情景可选参数。

无论谁使用该方法,只要提供一个db上下文就可以了。

您还可以添加额外的检查,以确保如果useDB为true,dbContext不会像我之前评论的那样为null。我编辑了我的问题
useDB
是一个参数,用于双重检查开发人员是否知道自己在做什么。闻起来了吗?看看我的编辑,你试图解决一个问题,因为你认为开发人员不会是白痴。这不是做这件事的方法。要么自己创建上下文,甚至不要担心他们试图传递上下文。或者只允许他们传递上下文,如果他们搞砸了,则返回null。他们的查询结果为空将非常明确地告诉他们,他们做错了什么。你也可以给他们一个错误。你试图这样做的方式是错误的做法。我想你根本不需要useDb。如果调用者认为它需要提供db,那么它无论如何都会提供。Robert C Martin在他的《干净代码》一书中提到了这一点。让布尔参数声明您正在调用的方法执行多项操作。Martin Fowler有一篇关于这个主题的有趣文章,与其使用标志,不如使用一个命名良好的方法@我编辑了我的问题。你认为我应该有两个功能吗
GetItemStatus
GetItemStatusWithContext
?@Marshall-没错,代码更清晰、更清晰。也更容易单独进行单元测试。我编辑了我的问题<不需要代码>useDB
。它是一个参数,用于双重检查开发人员是否知道他/她在做什么。它有味道吗?@Marshall:(1)如果有人忘记添加dbcontext参数,那就是他们的错误。您的布尔参数不会阻止错误的发生。这给每个人都制造了障碍,以防有人忘记了什么。这是一个比解决方案更大的麻烦。(2)
(fni==null)?true:false可以缩短为
(fni==null)
(3)就个人而言,我会包装该方法。如果需要,外部方法添加上下文,调用内部方法,然后处理上下文(如果是您的)。不管你从哪里得到上下文,内部方法都会处理db。@Marshall:但是在CodeReview.SE:)的新问题中最好有这样的讨论。谢谢,你说得对。也许今天晚些时候我会在CodeReview上发布一个问题