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.
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
I have a C# class that does some parsing of XML passed in to its one public method. The idea is that the method pulls info out of the XML, creates objects and sets up collections of them in public properties...
public class XmlParser {
public List<Customer> Customers { get; set; }
public void ProcessXml(string xml) {
XElement data = XElement.Parse(xml);
CreateEntities(Customers, data);
// do other stuff...
}
}
This way, we can do things like this in the calling code...
XmlParser xp = new XmlParser();
xp.ProcessXml(xml);
// do something with xp.Customers
I am trying to write a private generic method in the parser class, which would be used by the ProcessXml() method, and save me writing boilerplate code over and over again. The beginning of this method looks like this (other parameters missed out for clarity)...
private void CreateEntities<T>(List<T> collection, XElement data) {
if (collection == null) {
collection = new List<T>();
}
// process the XElement passed in, and add objects to the collection
}
I'm trying to use it like this...
CreateEntities(Customers, data);
...where the other parameters allow the compiler to know the generic type, and allow the method to know which entities to create etc.
However, the problem I have is that whilst the method itself works fine, and the collection variable is populated correctly, the public Customers property remains null.
I thought that passing a reference type, such as a List<> to a method allowed the method to modify the type, and have those changes seen outside the method, like in the answer from recursive in this SO post (I know that's a Dictionary, but I would have thought the principle would be the same).
Howcome my method can set collection to a new List<>, but Customers (which is the same object) remains null?
Update: Sigh, I ought to learn to read error messages!
Before I posted my question, I had tried passing the collection by ref, and it gave me compiler errors. I obviously didn't pay enough attention to the messages before moving on to plan B.
Having read the replies here, I tried ref again, and spotted that the compiler error was because I was trying to pass a public property by ref, which is not allowed. I changed the property from an automatic one to one with a backing field, passed the backing field by ref and it all works fine!
I thought that passing a reference type, such as a List<> to a method allowed the method to modify the type, and have those changes seen outside the method
You're getting confused with passing a parameter by reference (using the ref modifier), and passing a reference by value.
When you pass the value of a reference type (e.g. List<Customer>) to a method, you're still passing that argument by value by default. You can change the contents of the object that the variable's value refers to, but you can't change which object the original argument referred to, which is what you're trying to do.
Think about it like this... if I hand someone a piece of paper with my home address on, then they can do two things:
They can go to my house and paint my front door red
They can cross out my address and write a different address on the piece of paper
I will be able to see the result of the first action - it's changing something about the house itself. I won't be able to see the result of the second action, because it's just changing what's on the piece of paper... which is just a copy of what I know to be my home address.
For more details, refer to my article on parameter passing in C#.
To fix your problem, I would just change your CreateEntities method to return a list, rather than accepting one:
private List<T> CreateEntities<T>(XElement data)
{
var list = new List<T>();
// Populate the list...
return list;
}
If the caller wants to add those to an existing list, they can do so easily.
I think you missing the passing reference type by using ref. For more information ref (C# Reference)
Why is the code below
private static List<WorkflowVariableDataSet> MergeDatasetsListBranch(out List<WorkflowVariableDataSet> datasetsList)
{
if(datasetsList == null)
datasetsList=new List<WorkflowVariableDataSet>();
datasetsList=new List<WorkflowVariableDataSet>();
return datasetsList;
}
generating an error at the first if statement:
Out parameter 'datasetsList' might not be initialized before accessing.
I know it should be uninitialized at this point, but the word might suggest that the error lies in possible uninitialized object accessing (when it's not even accessed, it's the reference, that is checked). Ofc that doesn't happen with ref keyword, but I'm curious how is the reference checking violating out-parameters policy.
EDIT
I've edited the question and the example: the out object will be initialized inside the method anyway. The question is: WHY uninitialized object cannot be null compared? How is that different from:
object o;
if(o==null)
...
Compiler Error CS0269
Use of unassigned out parameter 'parameter' The compiler could not
verify that the out parameter was assigned a value before it was used;
its value may be undefined when assigned. Be sure to assign a value to
out parameters in the called method before accessing the value. If you
need to use the value of the variable passed in, use a ref parameter
instead.
So treat an out-parameter as unassigned. You are the one who is responsible.
So just remove the if:
datasetsList = new List<WorkflowVariableDataSet>();
If you want to process a list that is passed to this method use ref intead (as suggested above):
Because whether you've buggy code that never initialises the parameter, or buggy code that sometimes doesn't initialise it, it's still the same bug.
There's no point having a separate error message for the same bug depending on whether it hits in all or just one code paths; if there is a single code-path where the parameter is used before initialising, then it's has that error, and if there isn't a single code-path, then it doesn't.
So if we consider:
private static List<WorkflowVariableDataSet> MergeDatasetsListBranch(out List<WorkflowVariableDataSet> datasetsList)
{
if(_someBooleanField)
datasetsList = null;
if(datasetsList == null)
datasetsList=new List<WorkflowVariableDataSet>();
return datasetsList;
}
Here the use of an uninitialised out parameter might or might not happen, but that suffices to mean it has the same error.
As far as the error goes, there really isn't any significant difference between these two cases.
And therefore the error message uses might, even in cases where it will always apply.
Out arguments need not be initialized prior to being passed, the calling method is required to assign a value before the method returns.
Modified your code
private static List<WorkflowVariableDataSet> MergeDatasetsListBranch(out List<WorkflowVariableDataSet> datasetsList)
{
return datasetsList = new List<WorkflowVariableDataSet>();
}
This question already has answers here:
What's the difference between the 'ref' and 'out' keywords?
(28 answers)
Closed 4 years ago.
What is the difference between ref and out parameters in .NET? What are the situations where one can be more useful than the other? What would be a code snippet where one can be used and another can't?
They're pretty much the same - the only difference is that a variable you pass as an out parameter doesn't need to be initialized but passing it as a ref parameter it has to be set to something.
int x;
Foo(out x); // OK
int y;
Foo(ref y); // Error: y should be initialized before calling the method
Ref parameters are for data that might be modified, out parameters are for data that's an additional output for the function (eg int.TryParse) that are already using the return value for something.
Why does C# have both 'ref' and 'out'?
The caller of a method which takes an out parameter is not required to assign to the variable passed as the out parameter prior to the call; however, the callee is required to assign to the out parameter before returning.
In contrast ref parameters are considered initially assigned by the caller. As such, the callee is not required to assign to the ref parameter before use. Ref parameters are passed both into and out of a method.
So, out means out, while ref is for in and out.
These correspond closely to the [out] and [in,out] parameters of COM interfaces, the advantages of out parameters being that callers need not pass a pre-allocated object in cases where it is not needed by the method being called - this avoids both the cost of allocation, and any cost that might be associated with marshaling (more likely with COM, but not uncommon in .NET).
ref and out both allow the called method to modify a parameter. The difference between them is what happens before you make the call.
ref means that the parameter has a value on it before going into the function. The called function can read and or change the value any time. The parameter goes in, then comes out
out means that the parameter has no official value before going into the function. The called function must initialize it. The parameter only goes out
Here's my favorite way to look at it: ref is to pass variables by reference. out is to declare a secondary return value for the function. It's like if you could write this:
// This is not C#
public (bool, string) GetWebThing(string name, ref Buffer paramBuffer);
// This is C#
public bool GetWebThing(string name, ref Buffer paramBuffer, out string actualUrl);
Here's a more detailed list of the effects of each alternative:
Before calling the method:
ref: The caller must set the value of the parameter before passing it to the called method.
out: The caller method is not required to set the value of the argument before calling the method. Most likely, you shouldn't. In fact, any current value is discarded.
During the call:
ref: The called method can read the argument at any time.
out: The called method must initialize the parameter before reading it.
Remoted calls:
ref: The current value is marshalled to the remote call. Extra performance cost.
out: Nothing is passed to the remote call. Faster.
Technically speaking, you could use always ref in place of out, but out allows you to be more precise about the meaning of the argument, and sometimes it can be a lot more efficient.
Example for OUT : Variable gets value initialized after going into the method. Later the same value is returned to the main method.
namespace outreftry
{
class outref
{
static void Main(string[] args)
{
yyy a = new yyy(); ;
// u can try giving int i=100 but is useless as that value is not passed into
// the method. Only variable goes into the method and gets changed its
// value and comes out.
int i;
a.abc(out i);
System.Console.WriteLine(i);
}
}
class yyy
{
public void abc(out int i)
{
i = 10;
}
}
}
Output:
10
===============================================
Example for Ref : Variable should be initialized before going into the method. Later same value or modified value will be returned to the main method.
namespace outreftry
{
class outref
{
static void Main(string[] args)
{
yyy a = new yyy(); ;
int i = 0;
a.abc(ref i);
System.Console.WriteLine(i);
}
}
class yyy
{
public void abc(ref int i)
{
System.Console.WriteLine(i);
i = 10;
}
}
}
Output:
0
10
=================================
Hope its clear now.
A ref variable needs to be initialized before passing it in.
An out variable needs to be set in your function implementation
out parameters can be thought of as additional return variables (not input)
ref parameters can be thought of as both input and output variables.
Ref and Out Parameters:
The out and the ref parameters are used to return values in the same variable, that you pass as an argument of a method. These both parameters are very useful when your method needs to return more than one value.
You must assigned value to out parameter in calee method body, otherwise the method won't get compiled.
Ref Parameter : It has to be initialized before passing to the Method.
The ref keyword on a method parameter causes a method to refer to the same variable that was passed as an input parameter for the same method. If you do any changes to the variable, they will be reflected in the variable.
int sampleData = 0;
sampleMethod(ref sampleData);
Ex of Ref Parameter
public static void Main()
{
int i = 3; // Variable need to be initialized
sampleMethod(ref i );
}
public static void sampleMethod(ref int sampleData)
{
sampleData++;
}
Out Parameter : It is not necessary to be initialized before passing to Method.
The out parameter can be used to return the values in the same variable passed as a parameter of the method. Any changes made to the parameter will be reflected in the variable.
int sampleData;
sampleMethod(out sampleData);
Ex of Out Parameter
public static void Main()
{
int i, j; // Variable need not be initialized
sampleMethod(out i, out j);
}
public static int sampleMethod(out int sampleData1, out int sampleData2)
{
sampleData1 = 10;
sampleData2 = 20;
return 0;
}
out:
In C#, a method can return only one value. If you would like to return more than one value, you can use the out keyword. The out modifier returns as return-by-reference. The simplest answer is that the keyword “out” is used to get the value from the method.
You don't need to initialize the value in the calling function.
You must assign the value in the called function, otherwise the compiler will report an error.
ref:
In C#, when you pass a value type such as int, float, double etc. as an argument to the method parameter, it is passed by value. Therefore, if you modify the parameter value, it does not affect argument in the method call. But if you mark the parameter with “ref” keyword, it will reflect in the actual variable.
You need to initialize the variable before you call the function.
It’s not mandatory to assign any value to the ref parameter in the method. If you don’t change the value, what is the need to mark it as “ref”?
Ref parameters aren't required to be set in the function, whereas out parameters must be bound to a value before exiting the function. Variables passed as out may also be passed to a function without being initialized.
out specifies that the parameter is an output parameters, i.e. it has no value until it is explicitly set by the method.
ref specifies that the value is a reference that has a value, and whose value you can change inside the method.
out parameters are initialized by the method called, ref parameters are initialized before calling the method. Therefore, out parameters are used when you just need to get a secondary return value, ref parameters are used to get a value and potentially return a change to that value (secondarily to the main return value).
The ref keyword is used to pass values by reference. (This does not preclude the passed values being value-types or reference types). Output parameters specified with the out keyword are for returning values from a method.
One key difference in the code is that you must set the value of an output parameter within the method. This is not the case for ref parameters.
For more details look at http://www.blackwasp.co.uk/CSharpMethodParameters.aspx
An out parameter is a ref parameter with a special Out() attribute added. If a parameter to a C# method is declared as out, the compiler will require that the parameter be written before it can be read and before the method can return. If C# calls a method whose parameter includes an Out() attribute, the compiler will, for purposes of deciding whether to report "undefined variable" errors, pretend that the variable is written immediately before calling the method. Note that because other .net languages do not attach the same meaning to the Out() attribute, it is possible that calling a routine with an out parameter will leave the variable in question unaffected. If a variable is used as an out parameter before it is definitely assigned, the C# compiler will generate code to ensure that it gets cleared at some point before it is used, but if such a variable leaves and re-enters scope, there's no guarantee that it will be cleared again.
ref will probably choke on null since it presumably expects to be modifying an existing object. out expects null, since it's returning a new object.
out and ref are exactly the same with the exception that out variables don't have to be initialized before sending it into the abyss. I'm not that smart, I cribbed that from the MSDN library :).
To be more explicit about their use, however, the meaning of the modifier is that if you change the reference of that variable in your code, out and ref will cause your calling variable to change reference as well. In the code below, the ceo variable will be a reference to the newGuy once it returns from the call to doStuff. If it weren't for ref (or out) the reference wouldn't be changed.
private void newEmployee()
{
Person ceo = Person.FindCEO();
doStuff(ref ceo);
}
private void doStuff(ref Person employee)
{
Person newGuy = new Person();
employee = newGuy;
}
This The out and ref Paramerter in C# has some good examples.
The basic difference outlined is that out parameters don't need to be initialized when passed in, while ref parameters do.
They are subtly different.
An out parameter does not need to be initialized by the callee before being passed to the method. Therefore, any method with an out parameter
Cannot read the parameter before assigning a value to it
Must assign a value to it before returning
This is used for a method which needs to overwrite its argument regardless of its previous value.
A ref parameter must be initialized by the callee before passing it to the method. Therefore, any method with a ref parameter
Can inspect the value before assigning it
Can return the original value, untouched
This is used for a method which must (e.g.) inspect its value and validate it or normalize it.
out has gotten a new more succint syntax in C#7
https://learn.microsoft.com/en-us/dotnet/articles/csharp/whats-new/csharp-7#more-expression-bodied-members
and even more exciting is the C#7 tuple enhancements that are a more elegant choice than using ref and out IMHO.