Reputation: 29
Recently I came across a question which I was not very sure about. The scenario is :
Say we have a helper class : H and a method in helper class M1(int a, int b, int c) accepts three parameters. There are three classes which make use of this method : C1, C2, C3.
Now, we need another class C4 which also uses method M1 and will pass four parameters instead of three.
So, how do we tackle this problem.
Do we need Extension methods.?
Upvotes: 0
Views: 71
Reputation: 31116
You can use a default argument, but that has the issue that C1, C2 and C3 also get the overload with 4 arguments and C4 will get the overload with 3 arguments. The way you stated your question, I'm guessing that doesn't make sense (especially the C4 with 3 arguments usually doesn't make sense in real-life designs).
The way forward is to introduce a protected member and forward the calls. Basically your code will look something like this:
public class BaseClass
{
protected void H1B(int a, int b, int c, int d) { ... }
}
public class BaseClassFor3 : BaseClass
{
public void H1(int a, int b, int c) { H1B(a,b,c,0); } // forward call
}
public class C1 : BaseClassFor3 {} // etc
public class C2 : BaseClassFor3 {} // etc
public class C3 : BaseClassFor3 {} // etc
public class C4 : BaseClass
{
public void H1(int a, int b, int c, int d) { H1B(a,b,c,d); } // forward call
}
Adding a nullable or a parameter
Now here's a tricky question from @KAI: in what cases you you add a int? d
or another overload? Here goes.
As a rule of thumb, I always attempt to keep the functionality of a class independent of the functionality of other classes. This basically means that if you have C4, the code in the base classes shouldn't check for a condition that is implied by a sub class (such as C4).
So let's say we would have had this:
public void H1(int a, int b, int c, int? d) //...
usually this implies that somewhere down the line we would get this code:
if (d.HasValue)
{
// handle something that's specific for C4
}
Because this breaks the independency idea, I would never go for that.
Now there are two options:
As an example for (1): If you're familiar with f.ex. PDF applications, C1-C4 might actually be a vector operations on a 4x4 matrix. In such cases, some operations have 3 operands, and others have 4 operands. In the case where the operand is omitted, we usually implicitly mean 0
.
In this case, we add a common protected base class with an int
, and implement it like above. Note that there's no if
involved in the code of the base class; its functionality is isolated in the base class, like it should be.
In such a scenario, I would also use a Nullable
-- but if you start thinking about it like this, you'll notice that nullables will be very, very rare.
In scenario (2) the answer is different. For example, let's assume that H1 inserts something in a database. It makes little sense to implement shared code twice or copy-paste it. It's much better to isolate the code, create a separate method and call it from the 3/4 parameter implementation. It'll probably look like this:
public void H1(int a, int b, int c, int d)
{
// NOTE: this is just an example, I'd normally use an OR mapper!
// Construct query using a,b,c
string baseQuery = ConstructQuery(a,b,c);
baseQuery += " and d = " + d.ToString();
// ...
ExecuteSql(baseQuery);
// ...
}
Upvotes: 1
Reputation: 1271
You can overload the M1()
method using default parameter:
public static void M1(int a, int b, int c, int? d = null)
{
// working with a, b, c
if (d == null)
return;
var dValue = (int)d; // casting the nullable int to int to work with
// use the d parameter
}
In C1, C2, C3 you will call:
H1(1, 2, 3);
in C4 you will call:
H1(1, 2, 3, 4);
Note: the int?
makes the input parameter nullable
, so you can set it to null
. This way you won't have to choose a number as default parameter (which could be passed intentionally as well).
Upvotes: 2