Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parameter being optional or not, depending on previous parameter

Tags:

c#

.net

I have two methods:

Foo(int a, bool useDb)
Foo(int a, bool useDb, DbContext dbContext)

Is there a way to make it as ONE method, with those rules?
if useDb is true dbContext is mandatory
if useDb is false dbContext is optional

EDIT:

Just an edit to clarify, what I'm trying to do: In Business/Service layer, I have ItemService with method GetItemStatus. It connects to the database, get data and calculate the status.

There's nothing special. It creates a DbContext (EF6.0), do the thing and dispose it. Standard. But what if I want to use GetItemStatus as a part of different transaction? Ha!? I need to pass DbContext inside and do not dispose it obviously. I created something like this:

    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 ...
    }

But now I'm a little bit afraid, because if someone calls:

GetItemStatus(123456);

... and he forgot to add DbContext. I'm not sure if he actually means it. Altoguh it shouldn't be that bad. He will create new one and dispose it.

But I was thinking of the best way, to be sure that developer will not make a mistake. The "foolproof" way.

like image 487
Marshall Avatar asked Dec 03 '25 09:12

Marshall


1 Answers

There is no way to enforce a situationally optional parameter.

You can still make it an optional parameter and then manually throw an exception if the needed parameter was not supplied.

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

    //...
}

However, this will cause exceptions at runtime, and will not warn you at compile time. You'll end up having to bugfix the previously omitted db context, which is not the preferred approach.


I wonder what the need for the useDB boolean is. You can already derive that from whether a context was passed or not:

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

public void Foo(int a)
{
    //you already know useDB == false
}

This can also be put into a single method by making the dbcontext an optional parameter:

public void Foo(int a, DbContext dbContext = null)
{
    bool useDB = (dbContext != null);
}

This seems like a much cleaner approach. You omit a redundant parameter (useDB), which in turn forgoes the need for enforcing a situationally optional parameter.
Whoever uses the method will simply have to provide a db context if they want it to be used.

like image 63
Flater Avatar answered Dec 04 '25 22:12

Flater