Pass optional parameters to a method in a Dictionary (C#2.0) ?

A

Artie

Hi,

We have some test code where we would want to invoke a method with
optional parameters.

In C# 4.0, I believe we could use named parameters, but we're using C#
2.0

I found a Dictionary solved my problem, but I'm not sure it's the best
pattern for C# 2.0?.

Could anyone please comment on whether or not there's a more
appropriate pattern?

Cheers

artie

EXAMPLE:

public void AddToDatabase(Dictionary<string,object> fields)
{
string _surname = "";
string _city = "";
int _employeeId;

if (fields.ContainsKey("surname") _surname =
(string)fields["surname"];
if (fields.ContainsKey("city") _city = (string)fields["city"];
if (fields.ContainsKey("employee_id") _employeeId =
(int)fields["employee_id"];
....
// assemble SQL with the above parameters and execute SQL to write
to the database
....
}

USE:
public void Test()
{
....
Dictionary<string, object> fields = new Dictionary<string, object>();
fields.Add("surname", _localSurnameVariable);
....
fields.Add("city_id", _localCityVariable);
AddToDatabase(values);
....
}

public void AnotherTest()
{
....
Dictionary<string, object> fields = new Dictionary<string, object>();
// doesn't care about any other attributes, so only adds the
employee_id
fields.Add("employee_id", _localEmployeeId);
....
AddToDatabase(values);
....
}
 
W

Willem van Rumpt

Artie said:
Hi,

We have some test code where we would want to invoke a method with
optional parameters.

In C# 4.0, I believe we could use named parameters, but we're using C#
2.0

I found a Dictionary solved my problem, but I'm not sure it's the best
pattern for C# 2.0?.

Could anyone please comment on whether or not there's a more
appropriate pattern?

You could (sort of), but whether you should depends on what exactly you
want to achieve. The fact that everything relies on (hard coded) strings
makes it easy to make mistakes. Accidentally adding "Surname" instead of
"surname" to the dictionary will break the system. This could be
countered by either using constants (and praying that everyone in your
team will always use them), or by providing support routines (or using a
custom dictionary), to always convert to upper- or lowercase. Besides
the fragility of the code, it will also be a nightmare to maintain.

But from the provided example, it's hard to tell what the greater scheme
of things is. That makes it hard to suggest something better. The
"AddToDatabase" presumably is a somewhat generic method to render SQL to
add any kind of data to the database. Where does that data come from?

Is it important to know which fields are in the dictionary for the
AddToDatabase method? If not, it could also just simply regard the
key-value pairs as "fields with values that have to be emitted in SQL"
(although there doesn't seem to be a provision to specify a table in the
method).

Maybe there are classes in your model that are knowledgeable about how
to generate sql (a business objects in your domain might be repsonsible
for generating their own crud SQL for instance), without having to
resort to evaluating key-value pairs in a dictionary.
 
K

kndg

Hi,

We have some test code where we would want to invoke a method with
optional parameters.

In C# 4.0, I believe we could use named parameters, but we're using C#
2.0

I found a Dictionary solved my problem, but I'm not sure it's the best
pattern for C# 2.0?.

Could anyone please comment on whether or not there's a more
appropriate pattern?

Cheers

artie

EXAMPLE:

public void AddToDatabase(Dictionary<string,object> fields)
{
string _surname = "";
string _city = "";
int _employeeId;

if (fields.ContainsKey("surname") _surname =
(string)fields["surname"];
if (fields.ContainsKey("city") _city = (string)fields["city"];
if (fields.ContainsKey("employee_id") _employeeId =
(int)fields["employee_id"];
....
// assemble SQL with the above parameters and execute SQL to write
to the database
....
}

USE:
public void Test()
{
....
Dictionary<string, object> fields = new Dictionary<string, object>();
fields.Add("surname", _localSurnameVariable);
....
fields.Add("city_id", _localCityVariable);
AddToDatabase(values);
....
}

public void AnotherTest()
{
....
Dictionary<string, object> fields = new Dictionary<string, object>();
// doesn't care about any other attributes, so only adds the
employee_id
fields.Add("employee_id", _localEmployeeId);
....
AddToDatabase(values);
....
}

Hi,

I'm not sure why you go down that path... Isn't below would do what you
need?

public void AddToDatabase(string surname, string city, int employeeId)
{
// do something
}

public void AddToDatabase(int employeeId)
{
AddToDatabase("", "", employeeId);
}

// another overload for example
public void AddToDatabase(string surname, int employeeId)
{
AddToDatabase(surname, "", employeeId);
}

???

You can have as many method overloads you want.

Regards.
 
K

kndg

Hmm... okay, seems you're aftering the named parameter.
Your solution would do, but... hmm... hmm... maybe someone can suggest a
better approach?
 
A

Andy O'Neill

public void AddToDatabase(Dictionary<string,object> fields)
{
string _surname = "";
string _city = "";
int _employeeId;

if (fields.ContainsKey("surname") _surname =
(string)fields["surname"];
if (fields.ContainsKey("city") _city = (string)fields["city"];
if (fields.ContainsKey("employee_id") _employeeId =
(int)fields["employee_id"];
...
// assemble SQL with the above parameters and execute SQL to write
to the database
<<>>

Is this just to insert data in a regular database?

My first question in your position would be whether I could possibly instead
use a class per table.
Generics, typed lists and all that made .Net2 way easier.
Strongly typed means you don't have people breaking it like you can
dictionaries.

So - the thing to understand first is whether this is a data access layer
gone mad or there's some specific constraint/problem means you can't have a
class.

Generating the classes is relatively easy, I could provide a simplistic
application if you don't like ORM commercialy available.
 
A

Artie

Hi,

We have some test code where we would want to invoke a method with
optional parameters.

In C# 4.0, I believe we could use named parameters, but we're using C#
2.0

I found a Dictionary solved my problem, but I'm not sure it's the best
pattern for C# 2.0?.

Could anyone please comment on whether or not there's a more
appropriate pattern?

Cheers

artie

EXAMPLE:

public void AddToDatabase(Dictionary<string,object> fields)
{
   string _surname = "";
   string _city = "";
   int _employeeId;

   if (fields.ContainsKey("surname") _surname =
(string)fields["surname"];
   if (fields.ContainsKey("city") _city = (string)fields["city"];
   if (fields.ContainsKey("employee_id") _employeeId =
(int)fields["employee_id"];
...
   // assemble SQL with the above parameters and execute SQL to write
to the database
...

}

USE:
public void Test()
{
...
        Dictionary<string, object> fields = new Dictionary<string, object>();
        fields.Add("surname", _localSurnameVariable);
...
        fields.Add("city_id", _localCityVariable);
        AddToDatabase(values);
...

}

public void AnotherTest()
{
...
        Dictionary<string, object> fields = new Dictionary<string, object>();
    // doesn't care about any other attributes, so only adds the
employee_id
        fields.Add("employee_id", _localEmployeeId);
...
        AddToDatabase(values);
...

}

Thanks for all your responses guys, very much appreciated.

We did have 2 overloaded functions to begin with, but it looked like
we were going to end up with a large number, just to cope with each
individual scenario where different clients of the method would want
to omit certain parameters. So, C#4.0's named parameters would have
solved it perfectly.

I shouldn't have been so specific about what the method being called
is going to do with the data - just the fact that there IS a method
which has a number of clients, and we were looking for a way to handle
this without creating lots of overloaded functions - we have
previously used the pattern described by kndg.

The system we're working on is already a mess, and we're finding it
hard to work round bad designs.

The AddToDatabase method does already exist, but project contraints
(the usual - time and budget) mean that we can't refactor as much as
we'd like, so I wanted the quickest, best way to make this method
useable by a number of other methods, and making one version of it -
with the Dictionary - was the first thing that came to mind.

Thanks again for all your suggestions!

artie
 
P

Peter Duniho

Artie said:
[...]
We did have 2 overloaded functions to begin with, but it looked like
we were going to end up with a large number, just to cope with each
individual scenario where different clients of the method would want
to omit certain parameters. So, C#4.0's named parameters would have
solved it perfectly.

Opinions vary, of course. But my opinion is that if you'd have so many
parameters that the number of overloads would have been problematic,
then you'd have too many parameters to even go with named parameters.

Granted, I'm somewhat biased against named parameters anyway. They were
added to C# primarily as a solution to dealing with COM interop issues,
to reduce that as a "pain point". Lots of COM interfaces, especially
those from Office, have a very large number of optional parameters, and
along with the addition of the "dynamic" type, optional parameters are
intended mainly to help with that.

But of course, once something is in the language, people will use it for
other purposes too.

I think named parameters can help a lot when you have optional
parameters all of the same type, but even there one should be careful to
have very few parameters. IMHO, a method with more than three or four
parameters is asking for refactoring somehow, and once you get up to a
half-dozen or more, that just seems like a poor design choice.
I shouldn't have been so specific about what the method being called
is going to do with the data - just the fact that there IS a method
which has a number of clients, and we were looking for a way to handle
this without creating lots of overloaded functions - we have
previously used the pattern described by kndg.

The system we're working on is already a mess, and we're finding it
hard to work round bad designs.

If you're stuck with the design, you're stuck with it. But I think that
if there are so many optional parameters that overloading is
problematic, the dictionary-based approach is superior. I would use an
enum, rather than strings, as the key for the dictionary. That will
avoid spelling errors, etc.

Of course, if you have the opportunity to clean up the API itself so
that all these optional parameters aren't even needed, even better. But
obviously that's not always possible.

Pete
 
A

Artie

Artie said:

If you're stuck with the design, you're stuck with it.  But I think that
if there are so many optional parameters that overloading is
problematic, the dictionary-based approach is superior.  I would use an
enum, rather than strings, as the key for the dictionary.  That will
avoid spelling errors, etc.

Pete

Hi Pete,

Thanks for your response.

I've used Named Parameters in a very similar way, years ago, when I
used Ada. We used them for this very scenario and it worked well.

I agree that enum would give stronger typing, so I'll change it to use
enums rather than the strings.

Thanks

artie
 
A

Andy O'Neill

I agree that enum would give stronger typing, so I'll change it to use
enums rather than the strings.

I get that you don't want to refactor code and you're short of time.
My reasoning:

If you use enums you have to:
Generate the enums somehow for each table. Click, paste.
Change your update code to use them.

If you use classes and hand over a typed object (or obviate that bit of
code ) you have to.
Generate your classes somehow for each table. Click, paste.
Change all your update code to use them.

Obviously you know your staff and project better than I do.
On the face of it the two approaches seem likely to require similar effort.
Your code generation produces more text for a complete type but what the
hell.
Classes offer stronger typing (than enums) and other potential benefits such
as converting data format between the data store and view.
 
V

vanderghast

A class would be a great approach, even 3.0 allows object construction a
little bit like XML / F# ; like in here, for our object "titi":

----------------------
class Program
{
static void Main(string[] args)
{
toto titi = new toto { totoInt = 3,
totoString = "toto",
totoDouble = 3.4 };
}

}

internal class toto
{
public int totoInt;
public double totoDouble;
public string totoString;
public decimal totoDecimal;
}
--------------------

Sure, it is not exactly like what the OP describes, since the ***involved***
properties have to be known at coding time... but the same will hold for
using named parameters, no?


Vanderghast, Access MVP
 
A

Andy O'Neill

vanderghast said:
A class would be a great approach, even 3.0 allows object construction a
little bit like XML / F# ; like in here, for our object "titi":
Sure, it is not exactly like what the OP describes, since the
***involved*** properties have to be known at coding time... but the same
will hold for using named parameters, no?


Vanderghast, Access MVP

With straight .net 2 you'd have to create the object, set properties then
hand the project over.
Seems to me if the team have stopped writing code then just stick with the
approach as is.
If the team are still writing code then staying with an inherently faulted
approach is false economy.
Errm.
If it was economy.

Maybe there's something else we don't know.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top