I'm facing some problem in passing ConcurrentDictionary to another method with an out parameter.
In main method,
Method1(1,2,dictionary);
public override int Method1(int x,int y, out ConcurrentDictionary<string,int> dictionary)
{
if(dictionary.IsEmpty)
{
do something
}
}
The error message i got is "use of unassigned out parameter dictionary". And I need to preserve the content of dictionary throughout the codes. Appreciate for the help.
What do you think "out" means?
"out" is a bit like "ref". "ref" and "out" work with .NET reference types. "ref" indicates that the method can change the object the variable references. i.e. change what piece of memory the variable is pointing to. "out" indicates that it is expected that the method will define what object the variable references.
i.e. with out parameters you must instantiate the instance of the parameter within the method
e.g
public override int Method1(int x,int y, out ConcurrentDictionary<string,int> dictionary)
{
dictionary = new ConcurrentDictionary<string,int>();
// It doesn't make sense to check if it is empty here as it will always be empty
// if(dictionary.IsEmpty)
// {
Because dictionary is an out parameter, you have to guarantee that dictionary is assigned to by the time Method1 finishes. If you don't want to change dictionary, you could just assign it to itself.
Related
Earlier this week, C# 7.2 was released with the new feature of "in" parameter modifier see release notes here
The details provided in the release notes are:"The in modifier on parameters, to specify that an argument is passed by reference but not modified by the called method."
There is not a lot of documentation out on this new feature yet, so I have been trying it out. Seems to work as expected for primitive types, and prevents access to object properties. However, for lists you can still call the methods to modify a List (i.e. Add, Remove, Reverse) and you can actually modify an element directly.
static void Main(string[] args)
{
var test = new List<int>();
test.Add(5);
Console.WriteLine(test[0]);
TestMethod(test);
Console.WriteLine(test[0]);
}
public static void TestMethod(in List<int> myList)
{
myList[0] = 10;
myList.Add(7);
myList.Remove(2);
}
My question is, why can still modify collections when using the "in" parameter modifier?
The in modifier only restricts assigning to the reference, but the List<T> is still accessible and mutable. Basically it works like ref readonly.
You can't do myList = new List<int>.
These points from the documentation really clarifies the intent of the in modifier:
There are several ways in which the compiler ensures that the read-only nature of an in argument is enforced. First of all, the called method can't directly assign to an in parameter.
Ok so that means we cannot do this:
public void Something(in Point3D point1)
{
point1 = new Point3D(); // not allowed
}
It can't directly assign to any field of an in parameter.
Ok so that means we cannot do this as well:
public void Something(in Point3D point1)
{
point1.X = 10; // not allowed
}
In addition, you cannot pass an in parameter to any method demanding the ref or out modifier.
Ok so that means we cannot do below as well for obvious reasons because the method we are calling can set the reference which will break the above first rule:
public void Something(in Point3D point1)
{
SomethingElse(ref point1); // not allowed
}
public void SomethingElse(ref Point3D pointAnother)
{}
The compiler enforces that the in argument is a readonly variable. You can call any instance method that uses pass-by-value semantics. In those instances, a copy of the in parameter is created. Because the compiler can create a temporary variable for any in parameter, you can also specify default values for any in parameter.
So what I gather from the above is that you can pass a List<T> and the called method will be able to add items to it but it will not be able to assign another list to it or changes it's fields.
In Conclusion
Why can you still modify a List<> when it has the “in” parameter modifier in C# 7.2
You are allowed to do that because you are not breaking any of the rules.
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.
I have created a generic type to act as a pointer so that I can pass by reference. (Perhaps there is a much more simple way of doing this but I want to stress that I am doing this to learn more about generics and passing by reference, not the most efficient way of completing the task, if that makes sense.)
Here is the code I wrote for the generic type
class GenericPointer<T> {
public T item;
public void setItem(T i){ item = i; }
public T getItem(){ return item; }
}
In my program I have created an instance of this type called 'intPointer'. The value 143 is arbitrary.
GenericPointer<int> intPointer = new GenericPointer<int>();
intPointer.setItem(143);
Console.WriteLine(intPointer.getItem());
The above code runs properly, setting and returning the value 143.
I now want to pass this 'intPointer' to a method that increments it and then prints the value again.
So I wrote a method called addone()
public void addone(int i) { i ++; }
Now I want to make the following calls (remembering that I already set the value to 143):
Console.WriteLine(intPointer.getItem());
addone(intPointer);
Console.WriteLine(intPointer.getItem());
What I was expecting to see was 143 then 144 however I get the following errors:
The best overloaded method match for 'Notes.Program.addone(int)' has some invalid arguments
and:
cannot convert from 'Notes.GenericPointer<int>' to 'int'
Any help would be greatly appreciated!
I'll begin by correcting some of your terminology: you're not using pointers. C# does support pointers, but using the unsafe keyword, and they are real pointers (as in, integer memory addresses you can directly manipulate). The code you written is just an example of a boxed object.
.NET supports boxing already, by casting to Object; however it isn't recommended nor needed because the ref keyword solves the problem you're trying to "fix".
Use the ref keyword to describe a value-type parameter that should be passed by-reference instead of by-value. All other semantics remain the same, like so:
void Foo() {
int x = 123;
Bar(ref x);
Console.Write( x ); // prints "124".
}
void Bar(ref int x) {
x++;
}
I have a few other notes:
C# and .NET conventions dictate that all public members (methods, properties, fields, etc) should have TitleCase, not camelCase (i.e. ensure the first letter is capitalised).
Trivial getter and setter methods are discouraged, used Properties instead (though I note you cannot use ref arguments with properties).
You're getting your error because the type of intPointer is not int, but your class GenericPointer<int>.
While GenericPointer is wrapping an int, it is not actually an int so it cannot be treated as one. It has properties that are an int.
Imagine if GenericPointer wrapped a string. What would AddOne do to that.
You can act on the properties of the class but not treat the entire class as its generic type.
It would be possible to write an AddOne method that took a Generic Pointer argument and then inspected it for intyness and then added one to the internal item if it was an int. I am sure that is not a good idea.
What are you really trying to achieve with this GenericPointer?
If you want parameters to be reference if they are a value type (string, int, bool, etc.) then make your parameter like this:
public void addone(ref int i)
{
i++;
}
Then call the method like so:
addone(ref variableInt);
You can also look at this in order to see how to make your classes work as a specific type.
While using keyword ref, calling code needs to initialize passed arguments, but with keyword out we need not do so.
Why don't we use out everywhere?
What is exact difference between the two?
Please give example of a situation in which we need to use ref and can't use out?
The answer is given in this MSDN article. From that post:
The two parameter passing modes
addressed by out and ref are subtly
different, however they are both very
common. The subtle difference between
these modes leads to some very common
programming errors. These include:
not assigning a value to an out
parameter in all control flow paths
not assigning a value to variable
which is used as a ref parameter
Because the C# language assigns
different definite assignment rules to
these different parameter passing
modes, these common coding errors are
caught by the compiler as being
incorrect C# code.
The crux of the decision to include
both ref and out parameter passing
modes was that allowing the compiler
to detect these common coding errors
was worth the additional complexity of
having both ref and out parameter
passing modes in the language.
out is a special form of ref where the referenced memory should not be initialized before the call.
In this case the C# compiler enforces that the out variable is assigned before the method returns and that the variable is not used before it has been assigned.
Two examples where out doesn't work but ref does:
void NoOp(out int value) // value must be assigned before method returns
{
}
void Increment(out int value) // value cannot be used before it has been assigned
{
value = value + 1;
}
None of these answers satisfied me, so here's my take on ref versus out.
My answer is a summary of the following two pages:
ref (C# Reference)
out (C# Reference)
Compare
Both the method definition and the calling method must explicitly use the ref / out keyword
Both keywords cause parameters to be passed by reference (even value types)
However, there is no boxing when a value type is passed by reference
Properties cannot be passed via out or ref, because properties are really methods
ref / out are not considered to be part of the method signature at compile time, thus methods cannot be overloaded if the only difference between them is that one of the methods takes a ref argument and the other takes an out argument
Contrast
ref
Must be initialized before it is passed
Can use to pass a value to the method
out
Does not have to be initialized before it is passed
Calling method is required to assign a value before the method returns
Can not use to pass a value to the method
Examples
Won't compile because only difference in method signatures is ref / out:
public void Add(out int i) { }
public void Add(ref int i) { }
Using ref keyword:
public void PrintNames(List<string> names)
{
int index = 0; // initialize first (#1)
foreach(string name in names)
{
IncrementIndex(ref index);
Console.WriteLine(index.ToString() + ". " + name);
}
}
public void IncrementIndex(ref int index)
{
index++; // initial value was passed in (#2)
}
Using out keyword:
public void PrintNames(List<string> names)
{
foreach(string name in names)
{
int index; // not initialized (#1)
GetIndex(out index);
Console.WriteLine(index.ToString() + ". " + name);
}
}
public void GetIndex(out int index)
{
index = IndexHelper.GetLatestIndex(); // needs to be assigned a value (#2 & #3)
}
Author's Random Remarks
In my opinion, the concept of using the out keyword is similar to using the Output enum value of ParameterDirection for declaring output parameters in ADO.NET
Arrays in C# are passed by reference, but in order for a reassignment of the array reference to affect the reference in the calling code, the ref keyword must be used
Example:
public void ReassignArray(ref int[] array)
{
array = new int[10]; // now the array in the calling code
// will point to this new object
}
For more info on reference types versus value types, see Passing Reference-Type Parameters (C# Programming Guide)
A contrived example of when you'd need to use ref and not out is as follows:
public void SquareThisNumber(ref int number)
{
number = number * number;
}
int number = 4;
SquareThisNumber(ref number);
Here we want number to be an in-out variable, so we use ref. If we had used out, the compiler would have given an error saying we initialized an out param before using it.
The ref keyword allows you to change the value of a parameter. The method being called can be an intermediate link in the calling chain. A method using the out keyword can only be used at the beginning of a calling chain.
Another advantage is that the existing value can be used in the logic of the method and still hold the return value.
In Oracle functions have explicit IN (default and what you get if you don't set a direction) IN/OUT and OUT parameters. The equivalent is normal (just the parameter), ref [parameter], and out [parameter].
The compiler knows that out variables shouldn't set before the call. This allows them be just declared before use. However it knows that it must be set before the function it's used in returns.
When we pass the value while calling the method prefixed by the out keyword, it treats it entirely different like we are not passing it to the method. Instead we are actually collecting (outing) the value of the out variable from the definition section of the method to the method out variable parameter where we are calling that method.
So out variable is the output of processing done with in the method definition, and this is the reason why we need to create it, initialize it, and modify it within the definition only.
An out variable is used when we need return multiple values from a particular method.
While in case of a ref variable we need to initialize it first as its memory location is transfered to method definition as parameter. Think what would happen if we are not initializing it before passing?
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.