Related
I have two questions and I'd like some help with them, please.
I have client code that needs to access to a variable/value that is changing over time, in fact, it is calculated on retrieval, and it is retrieved by many methods several times over runtime, however, it's calculation is not always possible as the requirements for it are not always present, in such cases, a false or null is returned and the client checks this to decide wether to proceed. Now, I have two approaches, the first one, A, is my classic one, B however, looks good to me as well.
A) I have this method with an out parameter similar to the TryParse methods on some C# libraries:
public bool GetLeadingTrailSegment(out Vector3 lastTrailSegment)
{
if (_line.positionCount > 1)
{
lastTrailSegment = lead - _line.GetPosition(_line.positionCount - 2);
return true;
}
lastTrailSegment = Vector3.zero;
return false;
}
B) I have this nullable property which tries to do the same job as the above code:
public Vector3? leadingTrailSegment
{
get
{
if (_line.positionCount > 1)
{
return lead - _line.GetPosition(_line.positionCount - 2);
}
return null;
}
}
The client code is as follows:
A) Here the bool tells the client code wether the value is safe(useful?) to use.
public bool IsDrawingOverAllowed(LayoutPointer pointer)
{
Vector3 leadingTrailSegment;
if (pointer.GetLeadingTrailSegment(out leadingTrailSegment))
{
return !midline.ParallelTo(leadingTrailSegment);
}
return true;
}
B) Here, the fact of the HasValue property of the nullable being false tells the client wether it is safe:
public bool IsDrawingOverAllowed(LayoutPointer pointer)
{
Vector3? leadingTrailSegment = pointer.leadingTrailSegment;
if (leadingTrailSegment.HasValue)
{
return !midline.ParallelTo(leadingTrailSegment.Value);
}
return true;
}
First question: Of these two approaches, which one is best or what are the pros/cons between or flaws within them?
Second question: I used to have the client B approach written as:
public bool IsDrawingOverAllowed(LayoutPointer pointer)
{
if (pointer.leadingTrailSegment.HasValue)
{
return !midline.ParallelTo(pointer.leadingTrailSegment.Value);
}
return true;
}
This was wrong, right? Because the Value property of the nullable may have changed by the second call.
I like best the out parameter approach, you can use the result in the if clause, and the variable can even be declared inline in other versions of C# but I'd really like to give a shot to nullables and make them useful in situations like these (and not only when I look for an unassigned value, which are the cases I use them in). I hope someone can give their thoughts on this.
Thanks.
I would much prefer a call returning a null than using output parameters. Output parameters are a kind of "side-effect" prone code constructs that I personally really dislike. It means the calling code has to define a variable before use, and it introduces weak points where it would be easy to induce a bug if you put in the wrong variable in the call by accident. It also prevents you from using the code in a call chain with the null-conditional and null-coalescing operators. You cannot do something like var v = GetLeadingTrailSegment() ?? new Vector3();.
The second point of interest is the use of a Nullable. If the Vector3 type is a value type, then that is fine and makes sense. If it is a reference type (pretty much everything other than integral types and structures in .NET), there is no need for it. Just return null; and if (variable != null) { ... }. The case for returning a bool is usually when you have return value clashes. For example if null was returned as a valid value in itself, and you needed a way to differentiate between a valid null or an invalid response. This does not appear to be the case here.
My two cents :)
tldr:
I would rather ask why you want to have a method that returns a boolean but the name suggest another thing.
If I have player.GetCurrentHp() and the method returns false if the player has no hp or hp == 0, I would fell that the name is misleading and I would prefer have a player.isAlive() method.
Is not something wrong per se from a logic or software perspective, but I will not help the next developer to work with that code, or yourself in 6 months.
In your case I would go with two methods for LayoutPointer;
public bool IsValid() // <--- I like when boolean methods represent 'is, can, have' actions, ideas, or properties.
{
return _line.positionCount > 1;
}
and
public bool GetLeadingTrailSegment()
{
if (!IsValid())
{
return Vector3.zero;
}
return (lead - _line.GetPosition(_line.positionCount - 2));
}
And then;
public bool IsDrawingOverAllowed(LayoutPointer pointer)
{
if (pointer == null)
{
Debug.LogWarning("IsDrawingOverAllowed: Pointer is null!");
return true; // or false, it depends on your design..
}
if (!pointer.IsValid()) // <-- I also like early returns :D
{
return true;
}
var leadingTrailSegment = pointer.GetLeadingTrailSegment()
return !midline.IsParallelTo(leadingTrailSegment);
}
I know that can be more 'verbose' but remember the idea that create code for machines is easy, but code for humans is harder.. At the end you want to have some code easy to read, understand and maintain.
Side Note; Yes, I know that sometimes can be useful, like in Physics.Raycast but if you are not implementing the TryParse pattern (if you want for example avoid the use of try/catch) I cannot see much gain trying to have just one method that does two things.
is there a way to implement below scenario of function as a single call, so that for caller it looks like singe call (If not i can declare them as 2 overloaded calls, but checking if language has some feature)
Add(int, dateTime)
Add(datetime, int)
so that caller can call Add(2, DateTime.Now) Or Add(DateTime.Now, 2).
My scenario is that arguments to pass will come in an array, and i want caller can just call Add(args[0], args[1])
I can't use parameter name here as any parameter can be of any type. basically i want to have equivalent of
DateTime + int
int + dateTime
I would recommend just picking the order of arguments that makes sense to you, and sticking with that. Having multiple overloads of the exact same argument list in different orders is non-conventional and potentially confusing to consumers of your API.
One thing that can be done when calling methods is using Named Arguments. If your consumers use named arguments, they can put them in whatever order they want.
For example:
public static DateTime Add(int daysToAdd, DateTime date)
{
return date.AddDays(daysToAdd);
}
private static void Main()
{
// Call the method passing the int first, then the DateTime
var newDate1 = Add(daysToAdd: 5, date: DateTime.Now);
// Call the method passing the DateTime first, then the int
var newDate2 = Add(date: DateTime.Now, daysToAdd: 5);
}
No, there is no specific language feature for that.
In such cases you could use params object[] to give 0 or more parameters to the method, but I highly doubt that will ever give a decent working piece of code with is not error-prone. It means you have to cast every parameter to the desired type when you want to use them as such.
If you the types are hard-coded on the calling side, it is better to keep 1 single method.
define one of them, for exemple:
Add(int offSet, DateTime dataTime)
then use it like this
Add(offSet:2,dataTime:DateTime.Now)
Add(dataTime:DateTime.Now,offSet:2)
you can as well create a new method:
Add(DateTime dateTime, int offSet){
Add(offSet,dateTime );
}
I came across an example similar to this:
public Dictionary<string, object> generate(
string elementId,
Dictionary<string, object> additionalAttributes = null)
{
.... method body
}
Why would the dictionary passed as parameter be initiated to null? I haven't seen such construct. Does it have to do something with an optional parameter?
I can't speak to your first question, but the answer to your second question is yes. This is an optional parameter. C# only allows optional reference-type parameters to take a default value of null, except for string, which can take any constant string value, I believe.
Ref: MSDN
I use that to save time writing functions overloading. For example, instead of overloading two functions:
void SameFunctionName(Parameter1){ .. }
void SameFunctionName(Parameter1, Parameter2){ .. }
// maybe additional function body with three parameters .. etc
I just write one using this case:
void MyFunction(Parameter1, Parameter2 = null){ .. }
So, a small if statement inside my function would check if Parameter2 is null or not, to then make decisions. All in one function body.
and the function call for this case would work in both cases:
MyFunction(Parameter1); // This is a valid syntax
MyFunction(Parameter1, Parameter2); // This is a valid syntax
Optional parameter such as the one you use in your example can only be set to constant values, this means that you can't use any reference values, which is what Dictionary is, as such null is the only allowed value you can initialise an optional variable of type Dictionary to, if the method was using a value type like int or string then a value could be initialised for the optional parameter otherwise it has to be null
Yes it saves time if you are using Function Overloading For example this
can be avoided
Void Main()
{
fun1(11);
fun1(12,13);
}
public fun1(int i )
{
Print(i);
}
public fun1(int i ,int j)
{
Print(i+j);
}
This can be avoided by Code below and it also saves time and space
Void Main()
{
fun1(12);
}
public fun1(int i ,int j = NULL)
{
if(j==NULL)
Print(i);
else
Print(i+j);
}
This question already has answers here:
Should you declare methods using overloads or optional parameters in C# 4.0?
(13 answers)
Closed 9 years ago.
which one is better? at a glance optional parameter seems better (less code, less XML documentation, etc), but why do most MSDN library classes use overloading instead of optional parameters?
Is there any special thing you have to take note when you choose to use optional parameter (or overloading)?
One good use case for 'Optional parameters' in conjunction with 'Named Parameters' in C# 4.0 is that it presents us with an elegant alternative to method overloading where you overload method based on the number of parameters.
For example say you want a method foo to be be called/used like so, foo(), foo(1), foo(1,2), foo(1,2, "hello"). With method overloading you would implement the solution like this,
///Base foo method
public void DoFoo(int a, long b, string c)
{
//Do something
}
/// Foo with 2 params only
public void DoFoo(int a, long b)
{
/// ....
DoFoo(a, b, "Hello");
}
public void DoFoo(int a)
{
///....
DoFoo(a, 23, "Hello");
}
.....
With optional parameters in C# 4.0 you would implement the use case like the following,
public void DoFoo(int a = 10, long b = 23, string c = "Hello")
Then you could use the method like so - Note the use of named parameter -
DoFoo(c:"Hello There, John Doe")
This call takes parameter a value as 10 and parameter b as 23.
Another variant of this call - notice you don't need to set the parameter values in the order as they appear in the method signature, the named parameter makes the value explicit.
DoFoo(c:"hello again", a:100)
Another benefit of using named parameter is that it greatly enhances readability and thus code maintenance of optional parameter methods.
Note how one method pretty much makes redundant having to define 3 or more methods in method overloading. This I have found is a good use case for using optional parameter in conjunction with named parameters.
Optional Parameters provide issues when you expose them publicly as API. A rename of a parameter can lead to issues. Changing the default value leads to issues (See e.g. here for some info: Caveats of C# 4.0 optional parameters)
Also, optional params can only be used for compile-time constants. Compare this:
public static void Foo(IEnumerable<string> items = new List<string>()) {}
// Default parameter value for 'items' must be a compile-time constant
to this
public static void Foo() { Foo(new List<string>());}
public static void Foo(IEnumerable<string> items) {}
//all good
Update
Here's some additional reading material when a constructor with default parameters does not play nicely with Reflection.
I believe they serve different purposes. Optional parameters are for when you can use a default value for a parameter, and the underlying code will be the same:
public CreditScore CheckCredit(
bool useHistoricalData = false,
bool useStrongHeuristics = true) {
// ...
}
Method overloads are for when you have mutually-exclusive (subsets of) parameters. That normally means that you need to preprocess some parameters, or that you have different code altogether for the different "versions" of your method (note that even in this case, some parameters can be shared, that's why I mentioned "subsets" above):
public void SendSurvey(IList<Customer> customers, int surveyKey) {
// will loop and call the other one
}
public void SendSurvey(Customer customer, int surveyKey) {
...
}
(I wrote about this some time ago here)
This one almost goes without saying, but:
Not all languages support optional parameters. If you want your libraries to be friendly to those languages, you have to use overloads.
Granted, this isn't even an issue for most shops. But you can bet it's why Microsoft doesn't use optional parameters in the Base Class Library.
Neither is definitively "better" than the other. They both have their place in writing good code. Optional parameters should be used if the parameters can have a default value. Method overloading should be used when the difference in signature goes beyond not defining parameters that could have default values (such as that the behavior differs depending on which parameters are passed, and which are left to the default).
// this is a good candidate for optional parameters
public void DoSomething(int requiredThing, int nextThing = 12, int lastThing = 0)
// this is not, because it should be one or the other, but not both
public void DoSomething(Stream streamData = null, string stringData = null)
// these are good candidates for overloading
public void DoSomething(Stream data)
public void DoSomething(string data)
// these are no longer good candidates for overloading
public void DoSomething(int firstThing)
{
DoSomething(firstThing, 12);
}
public void DoSomething(int firstThing, int nextThing)
{
DoSomething(firstThing, nextThing, 0);
}
public void DoSomething(int firstThing, int nextThing, int lastThing)
{
...
}
Optional parameters has to be last. So you can not add an extra parameter to that method unless its also optional. Ex:
void MyMethod(int value, int otherValue = 0);
If you want to add a new parameter to this method without overloading it has to be optional. Like this
void MyMethod(int value, int otherValue = 0, int newParam = 0);
If it can't be optional, then you have to use overloading and remove the optional value for 'otherValue'. Like this:
void MyMethod(int value, int otherValue = 0);
void MyMethod(int value, int otherValue, int newParam);
I assume that you want to keep the ordering of the parameters the same.
So using optional parameters reduces the number of methods you need to have in your class, but is limited in that they need to be last.
Update
When calling methods with optional parameters, you can used named parameters like this:
void MyMethod(int value, int otherValue = 0, int newValue = 0);
MyMethod(10, newValue: 10); // Here I omitted the otherValue parameter that defaults to 0
So optional parameters gives the caller more possibilities.
One last thing. If you use method overloading with one implementation, like this:
void MyMethod(int value, int otherValue)
{
// Do the work
}
void MyMethod(int value)
{
MyMethod(value, 0); // Do the defaulting by method overloading
}
Then when calling 'MyMethod' like this:
MyMethod(100);
Will result in 2 method calls. But if you use optional parameters there is only one implementation of 'MyMethod' and hence, only one method call.
What about a 3rd option: pass an instance of a class with properties corresponding to various "optional parameters".
This provides the same benefit as named and optional parameters, but I feel that this is often much clearer. It gives you an opportunity to logically group parameters if necessary (i.e. with composition) and encapsulate some basic validation as well.
Also, if you expect clients that consume your methods to do any kind of metaprogramming (such as building linq expressions involving your methods), I think that keeping the method signature simple has its advantages.
A good place to use optional parameter is WCF since it does not support method overloading.
This is not really an answer to the original question, but rather a comment on #NileshGule's answer, but:
a) I don't have enough reputation points to comment
b) Multiple lines of code is quite hard to read in comments
Nilesh Gule wrote:
One benefit of using optional parameters is that you need not have to do a conditional check in your methods like if a string was null or empty if one of the input parameter was a string. As there would be a default value assigned to the optional parameter, the defensive coding will be reduced to a great extent.
This is actually incorrect, you still have to check for nulls:
void DoSomething(string value = "") // Unfortunately string.Empty is not a compile-time constant and cannot be used as default value
{
if(value == null)
throw new ArgumentNullException();
}
DoSomething(); // OK, will use default value of ""
DoSomething(null); // Will throw
If you supply a null string reference, it will not be replaced by the default value. So you still need to check the input parameters for nulls.
To address your first question,
why do most MSDN library classes use
overloading instead of optional
parameters?
It is for backward compatibility.
When you open a C# 2, 3.0 or 3.5 project in VS2010, it is automatically upgraded.
Just imagine the inconvenience it would create if each of the overloads used in the project had to be converted to match the corresponding optional parameter declaration.
Besides, as the saying goes, "why fix what is not broken?". It is not necessary to replace overloads that already work with new implementations.
One benefit of using optional parameters is that you need not have to do a conditional check in your methods like if a string was null or empty if one of the input parameter was a string. As there would be a default value assigned to the optional parameter, the defensive coding will be reduced to a great extent.
Named parameters give the flexibility of passing parameter values in any order.
Lets say I have a function that needs to return some integer value. but it can also fail, and I need to know when it does.
Which is the better way?
public int? DoSomethingWonderful()
or
public bool DoSomethingWonderful(out int parameter)
this is probably more of a style question, but I'm still curious which option people would take.
Edit: clarification, this code talks to a black box (lets call it a cloud. no, a black box. no, wait. cloud. yes). I dont care why it failed. I would just need to know if I have a valid value or not.
I like the nullable version better, because you can use the null coalesce operator ?? on it, e.g.:
int reallyTerrible = 0;
var mightBeWonderful = DoSomethingWonderful() ?? reallyTerrible;
It depends on how you think the calling code should look like. And therefore what your function is used for.
Generally, you should avoid out arguments. On the other hand, it could be nice to have code like this:
int parameter;
if (DoSomething(out paramameter))
{
// use parameter
}
When you have a nullable int, it would look like this:
int? result = DoSomething();
if (result != null)
{
// use result
}
This is somewhat better because you don't have an out argument, but the code that decides if the function succeeded doesn't look very obvious.
Don't forget that there is another option: use Exeptions. Only do this if the case where your function fails is really an exceptional and kind of a error-case.
try
{
// normal case
int result = DoSomething()
}
catch (SomethingFailedException ex)
{
// exceptional case
}
One advantage of the exception is that you can't just ignore it. The normal case is also straight forward to implement. If the exceptional case something you could ignore, you shouldn't use exceptions.
Edit: Forgot to mention: another advantage of an Exception is that you also can provide information why the operation failed. This information is provided by the Exception type, properties of the Exception and the message text.
Why not throw an exception?
I would follow the pattern used in some place in the .Net library like:
bool int.TryParse(string s, out value)
bool Dictionary.TryGetValue(T1 key, out T2 value)
So I would say:
public bool TryDoSomethingWonderful(out int parameter)
It really depends on what you are doing.
Is null a meaningful answer? If not, I would prefer a bool TryDoSomethingWonderful(out int) method call. This matches up with the Framework.
If, however, null is a meaningful return value, returning int? makes sense.
Unless performance is the primary concern you should return an int and throw an exception on failure.
I would use the second, because I probably need to know right away if the call succeeded, and in that case I would rather write
int x;
if( DoSomethingWonderful( out x ) )
{
SomethingElse(x);
}
than
int? x = DoSomethingWonderful();
if( x.HasValue )
{
SomethingElse(x.Value);
}
I am in favor of using an output parameter. In my opinion, this is the kind of situation for which use of an output parameters is most suited.
Yes, you can use the coalesce operator to keep your code as a one-liner if and only if you have an alternative value that you can use in the rest of your code. I often find that is not the case for me, and I would prefer to execute a different code path than I would if I was successfully able to retrieve a value.
int value;
if(DoSomethingWonderful(out value))
{
// continue on your merry way
}
else
{
// oops
Log("Unable to do something wonderful");
if (DoSomethingTerrible(out value))
{
// continue on your not-so-merry way
}
else
{
GiveUp();
}
}
Additionally, if the value that I want to retrieve is actually nullable, then using a function with an output parameter and a boolean return value is, in my opinion, the easiest way to tell the difference between "I was unsuccessful in retrieving the value" and "The value I retrieved is null". Sometimes I care about that distinction, such as in the following example:
private int? _Value;
private bool _ValueCanBeUsed = false;
public int? Value
{
get { return this._Value; }
set
{
this._Value = value;
this._ValueCanBeUsed = true;
}
}
public bool DoSomethingTerrible(out int? value)
{
if (this._ValueCanBeUsed)
{
value = this._Value;
// prevent others from using this value until it has been set again
this._ValueCanBeUsed = false;
return true;
}
else
{
value = null;
return false;
}
}
In my opinion, the only reason most people tend not to use output parameters is because they find the syntax cumbersome. However, I really feel that using output parameters is the more appropriate solution to this problem, and I found that once I got used to it I found the syntax much preferable to returning a null value.
If there's only one way it can fail, or if you'll never need to know why it failed, I'd say it's probably simpler and easier to go with the nullable return value.
Conversely, if there are multiple ways it could fail, and the calling code could want to know exactly why it failed, then go with the out parameter and return an error code instead of a bool (alternatively, you could throw an exception, but based on your question, it seems you've already decided not to throw an exception).
You should rather then use a try catch. This seems like the caller does not know what might happen?
Should we check both bool and the out, or should i check both returns null and the actual return.
Let the method do what it should, and in the case where it failed, let the caller know that it failed, and the caller hanlde as requied.
Interestingly enough, my personal opinion sways significantly based on the nature of the method. Specifically, if the method's purpose is to retrieve a single value, as opposing to "doing something".
Ex:
bool GetSerialNumber(out string serialNumber)
vs
string GetSerialNumber() // returns null on failure
The second feels more "natural" to me somehow, and likewise:
bool GetDeviceId(out int id)
vs
int? GetDeviceId() // returns null on failure`
But I admit this really falls into "coding style" territory.
Oh, and I, too, would tend to favor exception throwing:
int GetDeviceId() // throws an exception on read failure
I'm still not sold on why they'd be so wrong. Can we have a thread on that, Oren? ;-)
I dislike Microsoft's "Try" pattern in which the "out" parameter is used to return a data item. Among other things, methods coded in that fashion cannot be used in covariant interfaces. I would rather see a method coded as: T GetValue(out bool Successful) or perhaps T GetValue(out GetValueErrorEnum result); or T GetValue(out GetValueErrorInfo result); if something beyond a true/false might be needed. Since every data type has a legal default value, there's no problem with deciding what to return if the function fails. Calling code can easily say:
bool success;
var myValue = Thing.GetValue(ref success);
if (success)
.. do something using myValue
else
.. ignore myValue
It would be nice if .net and C# offered true covariant 'copy out' parameters (the caller would allocate space for the result, pass a pointer to that space to the called function, and then copy the allocated space to the passed-in variable only after the function returned).