Answered by:
c# default parameters to a method

Question
-
Hi
In c++ I used default parameter to a method
So If the calling function, does not send one of these parameters , it is OK.
Do you have it in C# ?
I don't mean method overloading , which requires two versions of quit a similar method
good morning sunshineMonday, June 6, 2011 4:47 PM
Answers
-
You do, but only in C# and .NET 4.0 (visual studio 2010). Prior to C# 4/VS2010, you had to explicitly overload each method.
You can do this in a way that's very similar to C++:
public void SomeMethod(string foo, int bar = 3, double baz = 42.0) { // Do something }
You can then call this as:
SomeMethod("foo");
or:
SomeMethod("foo", 4);
or even (which isn't allowed in C++):
SomeMethod("foo", baz: 55.0);
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".- Proposed as answer by Patrick Rodgers Monday, June 6, 2011 6:57 PM
- Marked as answer by gilit2 Tuesday, June 7, 2011 9:04 PM
Monday, June 6, 2011 5:00 PMModerator
All replies
-
- Proposed as answer by Patrick Rodgers Monday, June 6, 2011 6:57 PM
Monday, June 6, 2011 4:52 PM -
You do, but only in C# and .NET 4.0 (visual studio 2010). Prior to C# 4/VS2010, you had to explicitly overload each method.
You can do this in a way that's very similar to C++:
public void SomeMethod(string foo, int bar = 3, double baz = 42.0) { // Do something }
You can then call this as:
SomeMethod("foo");
or:
SomeMethod("foo", 4);
or even (which isn't allowed in C++):
SomeMethod("foo", baz: 55.0);
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".- Proposed as answer by Patrick Rodgers Monday, June 6, 2011 6:57 PM
- Marked as answer by gilit2 Tuesday, June 7, 2011 9:04 PM
Monday, June 6, 2011 5:00 PMModerator -
As an addendum, even though this is possible, it's not always a good idea, even in C# 4.0. You have to keep in mind several issues. For example, if SomeMethod is overridden in a child class, you can get different behaviors depending on how the method is invoked. Also, you may have some method ambiguity. For example, which method do you think gets called here?:
public void SomeMethod(string foo, int bar=3, double baz=42.0) { // Do stuff } public void SomeMethod(string foo) { // Do stuff } public void BreakStuff() { SomeMethod("Test"); }
The answer is that it really doesn't matter. The fact that you could write the code without knowing indicates that it's not a very good practice. It makes code harder to maintain.
That's my two cents anyway. There are cases where this can be useful, but I would suggest avoiding it unless you have a good reason to use it. It is likely to hurt in the long run if you use it often.
Monday, June 6, 2011 7:22 PM -
The fact that you could write the code without knowing indicates that it's not a very good practice. It makes code harder to maintain.
The fact that you could write the code without knowing which method will be called only means that you should read the C# Specifications. It's not even a difficult case. If the less specific method were called in that situation, how could you ever call the more specific one?The same thing could be told about overloading without optional parameters, or even hiding or overriding members. Do you think best practice would be to forbid virtual methods and have only globally unique identifiers for every member and local variable?
Tuesday, June 7, 2011 10:30 AM -
Another thing to keep in mind is that the optional parameter will be inlined at the calling location, it will not be determined at runtime. This means that optional parameters should not change their default value, as other assemblies will have inlined the old value and will keep using that instead. Unless the referencing assemblies are also recompiled.
If you need to be able to change the default value, use overloads instead.
Tuesday, June 7, 2011 1:14 PM -
Thank You all
Jesse , I am not shure , I understood you. Can you give an example ?
good morning sunshineTuesday, June 7, 2011 9:10 PM -
What Jesse was saying is that, when you write a program that uses an optional argument, the compiler "fills in" the value right then.
So, say you have a library, and it has a method:
static void Run(int amount = 42) { // Do something... }
If you make an application that uses this library (in a separate assembly [DLL]), and the main application does:
static void Main() { MyLibrary.Run(); }
The compiler sees that "Run" has an optional value (42), and turns this into:
static void Main() { MyLibrary.Run(42); }
This is compiled into the application.
If you later update the library, and change it to:static void Run(int amount = 43) { ...
The application will need to be recompiled against the new version. If you just replace the library, it will still run passing 42, since that's what the default parameter was set to when the application was compiled.
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".Tuesday, June 7, 2011 9:31 PMModerator -
There is a common workaround for what Reed is describing above.
Instead of making the default value the *actual* default that you want to use (42 in the example above), you make it a special value that will never need to change. That special value means "use *a* default value" rather than "use *this* default value".
Clearly it isn't always possible to choose such a value, but suppose for the example above that 'amount' would never ever be allowed to be int.MinValue.
Then you could write code like this:
static void Run(int amount = int.MinValue)
{
if (amount == int.MinValue)
{
amount = 42;
}
...
}That way, if you want to change the actual default value to something other than 42, you can just change that in the code without an application that uses the library needing to be recompiled.
If you ever wanted to change the int.MinValue special default value, then you'd have the same problem that Reed describes above. But if you just want to change the actual used default to something other than 42, there'd be no problem.
Tuesday, June 7, 2011 11:21 PM -
Maybe I'm the only one to think it's not a problem, it's a feature. If I'm initializing a new MyStorage with the default size of 1GB, I don't want my program to allocate 1TB when the next version of the dll gets released. If I want my program to take advantage of the new features, I recompile it.
If you want the default value to be dynamically determined, use overloads.
Wednesday, June 8, 2011 3:54 PM -
The fact that you could write the code without knowing indicates that it's not a very good practice. It makes code harder to maintain.
The fact that you could write the code without knowing which method will be called only means that you should read the C# Specifications. It's not even a difficult case. If the less specific method were called in that situation, how could you ever call the more specific one?The same thing could be told about overloading without optional parameters, or even hiding or overriding members. Do you think best practice would be to forbid virtual methods and have only globally unique identifiers for every member and local variable?
I'm not really sure I see what you're getting at here. How would you create a similar situation using overloads without optional parameters? Given that you cannot have any two methods with the same name and same signature, it's always immediately clear which method is being called when you have an overload, and there's never any need to read the C# specifications or even spend more than 30 seconds looking at it.
With optional parameters, I'm sure every possible situation is defined, but that doesn't change that it is difficult to read and easy for invokers to screw up. Anyone trying to call the method can easily accidentally call the wrong method without realizing it. I am always against any practice which makes errors easier when I'm writing any sort of externally-visible method.
EDIT TO ADD: On the idea of the default value being statically determined, it is a problem for two reasons. First, it takes control of the default value away from the implementer, which could introduce bugs if the implementer doesn't write it correctly. Second, it can get mixed up when you override a method with optional parameters (see the discussion here).Wednesday, June 8, 2011 6:20 PM -
I'm not really sure I see what you're getting at here. How would you create a similar situation using overloads without optional parameters? Given that you cannot have any two methods with the same name and same signature, it's always immediately clear which method is being called when you have an overload, and there's never any need to read the C# specifications or even spend more than 30 seconds looking at it.
You can have a situation identical to the simple "problem" with optional parameters:static void OverloadedMethod1(string p1, params string[] p2) { } static void OverloadedMethod1(params string[] p2) { } static void OverloadedMethod1(string p1) { }
or a bit more complicated:
static void OverloadedMethod2<T>(T p1, int i) where T : IEnumerable { } static void OverloadedMethod2(string p1, long i) { }
Which one will be called by OverloadedMethod("test", 42) is not as straightforward as your example.Friday, June 10, 2011 4:23 PM