What does it mean when a C# function parameter contains `= null`? - c#

I'm going through an MVC tutorial and see this line of code at the beginning of a function:
private void PopulateDepartmentsDropDownList(object selectedDepartment = null)
After testing it out, I can see that the function works, but I do not understand how the function parameter works. What does object selectedDepartment = null do?
I have done a general internet search and have not yet been able to locate an answer.
I guess my question really has two facets:
What does the = null portion of the parameter do?
Is it something that can be done but not necessarily should be done?

It means that that parameter will be null, unless you decide to pass something. So in other words, its optional.
It can be done, and there is nothing wrong with it. Its pretty common practice.

It means that you can call
PopulateDepartmentsDropDownList()
or
PopulateDepartmentsDropDownList("something")
both because compiler will convert the first one to
PopulateDepartmentsDropDownList(null)
This feature is called Optional Arguments
I suggest you to read this blog post

the = null is the default value of the parameter, it is the functional equivalent as if you had
private void PopulateDepartmentsDropDownList()
{
PopulateDepartmentsDropDownList(null);
}
private void PopulateDepartmentsDropDownList(object selectedDepartment)
{
//Your code here.
}
So if you can call the function with no parameters PopulateDepartmentsDropDownList() it will call the 1 perameter version and pass in null.

This sets the argument to a default value (if not provided) and prevents a compile time error if the argument is not provided. See:
Setting the default value of a C# Optional Parameter
Basically this argument is now optional so you can call the function in either of these two ways:
PopulateDepartmentsDropDownList() //selectedDepartment will be set to null as it is not provided
OR
PopulateDepartmentsDropDownList(myObject) //selectedDepartment will become myObject

Related

Find calls that specify a non-default value for an optional method parameter

I have a method:
public void MyMethod(Foo foo, int? optionalInt = null) {
// code I don't care about here
}
What I want to do is to find all calls to the method that specify a value for optionalInt. The method has over 200 references. If it's the only way, I'll go through them, but I'm hoping there is a better way.
I've realized that a partial answer is to delete the parameter and see where there are build errors. This is not always applicable, however. For example, if the parameter is part of an interface, there will also be build errors that are not related to what I want to find. For another example, if there are multiple such parameters, and this is not the last one, deleting it may not be so easy.

Is the in parameter modifier really optional on the call site?

I'm a bit confused about the in parameter modifier:
I know if I write in before a parameter it a read only reference, which is faster then passing big stuff by value. According to the documentation https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-parameter-modifier it says that the in parameter modifier is optional on the callsite:
Specifying in for arguments at the call site is typically optional. There is no semantic difference between passing arguments by value and passing them by reference using the in modifier. The in modifier at the call site is optional because you don't need to indicate that the argument's value might be changed. You explicitly add the in modifier at the call site to ensure the argument is passed by reference, not by value. Explicitly using in has the following two effects:
First, specifying in at the call site forces the compiler to select a method defined with a matching in parameter. Otherwise, when two methods differ only in the presence of in, the by value overload is a better match.
Second, specifying in declares your intent to pass an argument by reference
When I use it in my code:
public static kAssetKind? DetermineAssetKind(in string extension)...
And I call it here:
...{FilePath = mainFile, Kind = DetermineAssetKind(Path.GetExtension(mainFile)) ?? kAssetKind.Other};
it's okay the string is passed by reference, but if I write specifically in before:
DetermineAssetKind(in Path.GetExtension(mainFile))
then I get an error that it could be passed by reference. So there is a difference between an in on callsite and it says "Second, specifying in declares your intent to pass an argument by reference" but I thought it will pass it by reference even if I don't use in at the callsite? And does it even make sense to pass a string as in reference because classes are reference?
I think you are misunderstanding the article.
The way I understand it is that considering the following method:
void Foo(in SomeBigValueType t)
{ ... }
The following two calls are the same:
SomeBigValueType v;
Foo(v);
Foo(in v);
Your issue seems to be unrelated to the article. in needs a storage location (aka variable). In your second example you aren’t passing one so you get an error; you’d get the same error with ref or out.

Named Parameters vs Optional Parameters

The optional parameters are nothing new in C# and I've known about that since the release of C# 5.0 but there is something I just came across. When I use Data Annotations for my MVC models such as the Required attribute I see this:
So I can do:
[Required(ErrorMessage="Something"]
However when I create my own methods with optional parameters like:
void Test(String x = null, String y = null) {}
I can pass arguments in both these ways:
Test(x = "Test") OR Test(x: "Test")
this while in the Required attribute I always have to use the = and if I use the : it will cause error.
for example:
Required(ErrorMessage:"Something") --> Compile time error
So what I see is that those Named Parameters are created differently than what I already knew about. And my question is How to make them for a method (How to create such Named Parameters like in the Required attribute).
An attribute has its own syntax. It uses the name=value form for named parameters.
For a normal method you can't use that form, you are stuck with the name:value form.
It would not be possible to use the name=value form for normal methods. The compiler would not be able to tell if you were trying to use a named parameter or if you were trying to assing a value to a variable and use the assignment as a parameter value.
Despite this syntax looking like a method call:
[Required(ErrorMessage="Something")]
An Attribute is a class, not a method. You aren't specifying an argument in the line above, you are initializing a property. See the example on the Attribute base class documentation to see what I mean.
The Attribute-specifying syntax is therefore similar to C#'s class initialization syntax:
new RequiredAttribute { ErrorMessage = "Something" };
There is currently no equivalent syntax in C# for specifying a named argument to a method.
If you do something like:
string y;
Test(y = "Test")
You can call a function with that syntax. But be careful... the y = "Test" is actually setting the variable y, and then passing that to the function! There is a side-effect there which is probably undesirable. Also "Test" is getting passed into parameter x of the Test function, not y because it's going in as the first parameter.
In short, you should always avoid using this syntax when calling a function, because it doesn't do what you're expecting.

In C#, can I send an out parameter to be used elsewhere

I have a function that is getting called by another part of the code, with the signature:
public override bool DoSomething(Foo f, out string failed)
{
failed = "I failed";
_anotherClassMethodExpectingString.SetString(failed);
}
So my question is - If i need to send the other class method the same string that my caller is expecting back in its "out" parameter, can i just send it the same variable, without having any effect on my caller? The "out" parameter is a little confusing to me .. Should I have used something like this instead:
public override bool DoSomething(Foo f, out string failed)
{
string localStr = "I failed";
failed = localStr;
_anotherClassMethodExpectingString.SetString(localStr);
}
Unless the subsequent method you're calling is also using an out parameter then there's no need to define a local variable. The string will be unaffected by any regular parameter passing.
If you do not expect or do not desire for your method's caller to see any alteration from the third method, what you have is fine. If I am reading your question correctly, this seems to be your intent.
If you wanted your caller to reflect changes introduced by the third method, it would need to be an out parameter there as well, or instead return the modification via a return value which you would then assign to your original out parameter prior to returning.
If a parameter is declared for a method without ref or out, the parameter can have a value associated with it. That value can be changed in the method, but the changed value will not be retained when control passes back to the calling procedure.
Given that strings are immutable in .NET, it is safe to pass failed to any method without ref and out on the string parameter and be sure it won't be changed.
The out parameter is like pointer of the object in c++. So if you don't use 'out' definer ,doesn't change value of the parameter.

Assignment operator (=) in argument of Method Definition

See below method definition.
What is it called in C# where the equals sign is in method parameter.
Does it default method parameter initialization??
public List<Iabc> MyMethod(out List<Ixyz> faces, Type typeXYZ = null, int flag = -1)
{
//...
//...
}
NOTE: Here Iabc and Ixyz are any Interfaces.
They're called optional (or named) arguments. MSDN usually has these things explained pretty well:
Named and Optional Arguments (C# Programming Guide)
When using named arguments, be aware that changing argument names will break code. (where named parameters are used)
Also, remember that the default value is actually stored in the call site meaning that if you at some later point change the default value, code that is calling the method and was compiled before the change, will still use the old value. it might not matter in all situations but its something to be aware of.
That's an optional argument in C# 4.0

Categories

Resources