As a newbie I've read about the dangers of passing parameters with the ref keyword. I guess there's great potential to mess up code when a ref variable is modified in part of a program which then changes what happens elsewhere. Objects end up being very tightly coupled. (I recognize there may be places where ref is worthwhile.) What I don't yet know, and am asking about, are the alternatives.
In one program, for example, I create a generic list at startup, which I manipulate in the program's methods. In one method:
//a user is asked a question
//if the response is yes, the list is modified one way and the method returns true
//if the response is no, the list is modified a different way and the method returns false.
So the method returns a Boolean and I pass the list in as a ref. I have several similar methods, each asking users unique questions and then modifying the list in some way.
It seems like a typical alternative might be to bundle the list and a Boolean field into its own class. Somehow this seems like creating an object for nothing more than convenience, just to hold two pieces of data, with no connection to any real world entity.
So, how would you (pseudo)code a method that returns both a generic list and a Boolean value?
EDIT: Here's some actual code
private static bool AskExptQuestion(ref List<StatTest> testList)
{
Console.Write(Constants.ExptQText); //experimental groups?
string response = Console.ReadLine();
//if response==y, it's experimental
if (response == "y")
{
//so select all experimental
var q1List =
from test in testList
where test.isExperimental == true
select test;
//to copy resulting IEnumerable<List> (q1list) to generic List, must copy/cast IEnumerable to a List<t>
testList = q1List.ToList();
return true;
}
//and if response==n, it's not experimental
else
{
//so select all non-experimental
var q1List =
from test in testList
where test.isExperimental == false
select test;
testList = q1List.ToList();
return false;
}
}
Returning a list (or almost anything else, for that matter) along with its characteristic, such as a Boolean value, is a "poster child" of the ref/out feature. This pattern is used in several places in the standard .NET library:
Dictionary.TryGetValue uses this pattern, returning true or false depending on presence of the key in the dictionary, and setting a out to the return object
Integer.TryParse (and other numeric types) use this pattern, returning true when the parse is successful, and setting the value in a out parameter
The difference between ref and out is that ref gives your method an option to keep the old object/value or to supply a new one, while the out forces you to supply a new one before the method returns.
There is no point to create a new class simply to bundle two unrelated types together.
In addition, it is important to understand that modifications to method parameters can happen even in situations when a parameter is not passed by ref or out. When you pass an object of reference (i.e. class) type that is mutable, any modifications to the object done inside the method are visible in the caller.
The only difference when passing by ref or out is that you are allowed to replace the object itself with a new one, while passing a reference type without ref is restricted to mutating the incoming object itself.
From reading your example and comments, it sounds like you might just want the ability to apply some filters to a collection. Why not have your functions return the filters?
private static Predicate<StatTest> AskExptQuestion()
{
Console.Write(Constants.ExptQText); // experimental groups?
bool response = Console.ReadLine() == "y"; // maybe wrap this up in a function to read a yes/no answer
return t => t.isExperimental == response;
}
You might still need that bool return value, though, which can become an out parameter. It’s not clear what that’s for.
in c# paramaters are passed by value.
object types (classes) are implimented by a pointer to an instance in memory.
where passing an object to a method, the pointer is copied to the argument and he then points to the same instance.
if i have:
void foo(MyClass param)
{
param.x = 7;
}
and somewhere else i do:
MyClass obj = new MyClass();
obj.x = 5;
foo(obj);
then after the call to foo() the x property of obj is 7.
if foo is:
void foo(MyClass param)
{
param = new MyClass();
param = 7;
}
then my original obj will still have x equals to 5. this is because i ran over the instance that param was looking at.
now the "ref" keyword:
void foo(ref MyClass param)
{
param = new MyClass();
param = 7;
}
if i call like this:
MyClass obj = new MyClass();
obj.x = 5;
foo(ref obj);
in this combination my obj will be set to the new instance of MyClass and will have x equals 7. the ref means that the variable in the method is the same as the variable passed, and not just pointing to the same instance to start with.
Related
I would like to make use of out or ref parameters that may not be assigned prior to calling the function. The function then is responsible for checking whether the parameter exists, and if not, creates and returns a new object.
Here is some example C# code for what I'm trying to accomplish:
public virtual object MyFunction(out object myObject)
{
if (myObject == null)
myObject = new Object();
// do some more things here...
// maybe return myObject, or perhaps something else
return myObject;
}
I would like each of the four example function calls below to be considered valid:
Object x = new Object();
MyFunction(x); // x gets passed by reference
Object y = MyFunction(x);
Object z = MyFunction();
Object u = MyFunction(null);
I get an error on line 3 telling me that Out parameter 'list' might not be initialized before accessing. Attempting to give myObject a default value gives the error A 'ref' or 'out' parameter cannot have a default value.
Is there a way to use out parameters (pass by reference) and check to see if those references have been initialized before assigning them to anything?
No, this is not possible. If you use an out parameter then you are not permitted to read the value before assigning to the variable, for the reason the compiler has already told you. If you use ref then the parameter must be initialized before it is allowed to be passed in.
Return values are most of the time the right choice when the method doesn't have anything else to return.
It only stops the caller from having to declare the variable separately. Example:
int x1;
GetValue(out x1);
Declaring a variable:
int? x1 = GetValue();
You can read more about it in thi MSDN documentation.
When you pass a null as your out parameter, e.g. by using out _, the CLR will allocate temporary storage when you first use the parameter so there is no need for the initial check that won't compile.
Step over this line (there is no exception):
The call was double result = TestMethods.DoubleValue(2.5, out _);
I have class that defines the following methods -
void DoAction1(out object result1)
{
// Do some work and set result1
}
void DoAction2(out object result2)
{
// Do some work and set result2
}
void ExecuteAllActions()
{
//Some more execution work happens here
// which may cause modifications to result1 and result2
}
Is there some way I can store a ref to the two out params and update them in ExecuteAllActions() function?
With the limited amount of information you have provided, all I can say is that you are doing it wrong. As a general rule, you never write a method with an out parameter and a void return type, since you can just return whatever object you would have assigned to the out parameter. This type of approach is much easier and simpler:
object DoAction1()
{
// Do some stuff and return a result object
}
object DoAction2()
{
// Do some stuff and return a result object
}
void ExecuteAllActions()
{
var actionResult1 = DoAction1();
var actionResult2 = DoAction2();
}
There is -- deliberately -- no way in the .NET type system to store a ref to a variable. This at a stroke avoids the problem of storing a reference to a variable whose lifetime has ended.
However, I note that a one-element array is an object that can be passed as a reference type, whose sole element is a variable that can be passed as ref or out. Obviously you can store a one-element array, pass it around as you like and so on.
That said, if you need to resort to tricks like this, something is probably wrong in the design. Try to make APIs that take values and return values, not take variables and mutate them.
I have two methods:
public void A(List<int> nums)
{
nums.Add(10);
}
public void B(out List<int> nums)
{
nums.Add(10);
}
What is the difference between these two calls?
List<int> numsA = new List<int>();
A(numsA);
List<int> numsB = new List<int>();
B(out numsB);
In general, I am trying to understand the difference between passing reference types as-is or as out parameters.
In your example, method B will fail to compile, because an out parameter is considered to be uninitialized, so you have to initialize it before you can use it. Also, when calling a method with an out parameter, you need to specify the out keyword at the call site:
B(out numsB);
And you don't need to initialize the numbsB variable before the call, because it will be overwritten by the method.
Jon Skeet has a great article that explains the various ways to pass parameters: Parameter passing in C#
A non-ref, non-out parameter, like a local variable, denotes a storage location. If the storage location's type is a reference type, then the storage location holds a reference to an instance of that type.
Ref and out parameters, by contrast, hold a reference to a storage location. That storage location could be a local variable, a field, or an array element. In other words, ref and out parameters introduce another layer of indirection. If you have a reference-type ref or out parameter in a method, it therefore represents a reference to a reference to an object.
Why would you want a reference to a reference to an object? In case you need to modify the reference to the object (as opposed to modifying the object itself).
This is a useful technique in some narrow circumstances. For example, you might want to write a function that orders two queues depending on which has the smaller value on top:
void OrderQueues(ref Queue<int> a, ref Queue<int> b)
{
if (a.Peek <= b.Peek) return;
var temp = a;
a = b;
b = temp;
}
Out parameters are useful if you want to return more than one value from a method:
void OldestAndYoungest(IEnumerable<Person> people, out Person youngest, out Person oldest)
{
youngest = null;
oldest = null;
foreach (var person in people)
{
if (youngest == null || person.Age < youngest.Age)
youngest = person;
if (oldest == null || oldest.Age < person.Age)
oldest = person;
}
}
In my experience, ref and out parameters are fairly rare, and even rarer with reference types.
Note that a ref parameter must be initialized by the caller, while an out parameter must be initialized by the callee. If you never assign a value to the ref parameter, then it should probably be a "normal" parameter. If you never assign a value to an out parameter, as in your example, your code will not compile.
In version B, the function has direct access to the variable. It's like the 'ref' keyword, except that the variable must be assigned from within the function taking the parameter. It lets you return multiple values from a function. And the call syntax is 'B(out numsB);'
The out keyword causes arguments to be passed by reference. This is
similar to the ref keyword, except that ref requires that the variable
be initialized before being passed. To use an out parameter, both the
method definition and the calling method must explicitly use the out
keyword. For example:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
When to pass ref keyword in
Hi All,
I am just surprised that why we have ref in C# while by default everything which is a reference type in C# is passed as a reference.
In simpler words, can anyone explain me the difference between these two method calls:
public void Test(SomeClass someClass)
{
// some code here
}
and
public void Test(ref SomeClass someClass)
{
// some code here
}
In my thinking they both have reference to same memory location.
So why do we need ref keyword at all ?
The ref keyword passes in a reference to whatever location is storing the reference. This allows you to manipulate this variable from the called function. This is particularly useful for value types, but also has uses when used with reference types. (Dictionary.TryGetValue() being a good example. The out parameter is required to return the value stored in the dictionary. out is equivalent to ref except that it will undergo a different set of compile-time checks.)
For example:
public void Test(ref SomeClass obj)
{
obj = null;
}
public void Test2(SomeClass obj)
{
obj = null;
}
public void Foo()
{
SomeClass obj = new SomeClass();
Test(ref obj);
// obj is null here!
obj = new SomeClass();
Test2(obj);
// obj is not null here.
}
I am just surprised that why we have ref in C# while by default everything is which is a reference type in C# is passed as a reference.
Because some things in C# are value types, and sometimes we want to pass those. We have the ref keyword so that those things can be passed by reference also.
It's analogous to the difference between a SomeClass * and a SomeClass ** in C++.
With a SomeClass * (or without ref), we can modify the object pointed to, but we can't redirect it to an entirely new object.
With a SomeClass ** (or with ref), we can change the argument in the calling code in order to point it to an object of our choosing.
When you pass an object you pass it by reference. This means that anything you do to that object will be reflected in the object after the method returns. When you pass the reference by reference i.e. void Foo(ref object obj) you are passing the address of that object. You can then re-assign the address to a different object and that will be the state of things when the method returns
foo (object o)
{
...
}
var v = new object();
foo(v);
v will still reference the same object that was instantiated prior to the call to foo
void bar(ref object o)
{
o = null;
}
var v = new object();
foo(ref v);
// v is now null
Suppose method Foo accepts a Bar by value. If I have a Bar called "Boz", the statement:
Foo(Boz);
may take the object pointed to by Boz and change that object's characteristics, but it cannot change which object Boz points to. By contrast, if Boz were passed by reference, the same statement could cause Boz to point to a different object entirely.
As an example of usage, consider a routine that accepts an array as a parameter. If an array is passed by value, the recipient can change the value of any of the items in the array, but the recipient cannot change the size. The only way to change the size of an array is to create a new array, copy the old items into it, and from thence forth use the new array instead of the old one. When an array passed by value, there is no way for the recipient to tell the caller that it should stop using the old array and use the new one instead. With an array passed by reference that is not a problem.
Can you please tell me what is the exact use of out parameter?
Related Question:
What is the difference between ref and out? (C#)
The best example of a good use of an out parameter are in the TryParse methods.
int result =-1;
if (!Int32.TryParse(SomeString, out result){
// log bad input
}
return result;
Using TryParse instead of ParseInt removes the need to handle exceptions and makes the code much more elegant.
The out parameter essentially allows for more than one return values from a method.
The out method parameter keyword on a
method parameter causes a method to
refer to the same variable that was
passed into the method. Any changes
made to the parameter in the method
will be reflected in that variable
when control passes back to the
calling method.
Declaring an out method is useful when
you want a method to return multiple
values. A method that uses an out
parameter can still return a value. A
method can have more than one out
parameter.
To use an out parameter, the argument
must explicitly be passed to the
method as an out argument. The value
of an out argument will not be passed
to the out parameter.
A variable passed as an out argument
need not be initialized. However, the
out parameter must be assigned a value
before the method returns.
An Example:
using System;
public class MyClass
{
public static int TestOut(out char i)
{
i = 'b';
return -1;
}
public static void Main()
{
char i; // variable need not be initialized
Console.WriteLine(TestOut(out i));
Console.WriteLine(i);
}
}
http://msdn.microsoft.com/en-us/vcsharp/aa336814.aspx
Out parameters are output only parameters meaning they can only passback a value from a function.We create a "out" parameter by preceding the parameter data type with the out modifier. When ever a "out" parameter is passed only an unassigned reference is passed to the function.
using System;
class ParameterTest
{
static void Mymethod(out int Param1)
{
Param1=100;
}
static void Main()
{
int Myvalue=5;
MyMethod(Myvalue);
Console.WriteLine(out Myvalue);
}
}
Output of the above program would be 100 since the value of the "out" parameter is passed back to the calling part. Note
The modifier "out" should precede the parameter being passed even in the calling part. "out" parameters cannot be used within the function before assigning a value to it. A value should be assigned to the "out" parameter before the method returns.
Besides allowing you to have multiple return values, another use is to reduce overhead when copying a large value type to a method. When you pass something to a method, a copy of the value of that something is made. If it's a reference type (string for example) then a copy of the reference (the value of a reference type) is made. However, when you copy a value type (a struct like int or double) a copy of the entire thing is made (the value of a value type is the thing itself). Now, a reference is 4 bytes (on 32-bit applications) and an int is 4 bytes, so the copying is not a problem. However, it's possible to have very large value types and while that's not recommended, it might be needed sometimes. And when you have a value type of say, 64 bytes, the cost of copying it to methods is prohibitive (especially when you use such a large struct for performance reasons in the first place). When you use out, no copy of the object is made, you simply refer to the same thing.
public struct BigStruct
{
public int A, B, C, D, E, F, G, H, J, J, K, L, M, N, O, P;
}
SomeMethod(instanceOfBigStruct); // A copy is made of this 64-byte struct.
SomeOtherMethod(out instanceOfBigStruct); // No copy is made
A second use directly in line with this is that, because you don't make a copy of the struct, but refer to the same thing in the method as you do outside of the method, any changes made to the object inside the method, are persisted outside the method. This is already the case in a reference type, but not in value types.
Some examples:
public void ReferenceExample(SomeReferenceType s)
{
s.SomeProperty = "a string"; // The change is persisted to outside of the method
}
public void ValueTypeExample(BigStruct b)
{
b.A = 5; // Has no effect on the original BigStruct that you passed into the method, because b is a copy!
}
public void ValueTypeExampleOut(out BigStruct b)
{
b = new BigStruct();
b.A = 5; // Works, because you refer to the same thing here
}
Now, you may have noticed that inside ValueTypeExampleOut I made a new instance of BigStruct. That is because, if you use out, you must assign the variable to something before you exit the method.
There is however, another keyword, ref which is identical except that you are not forced to assign it within the method. However, that also means you can't pass in an unassigned variable, which would make that nice Try.. pattern not compile when used with ref.
int a;
if(TrySomething(out a)) {}
That works because TrySomething is forced to assign something to a.
int a;
if(TrySomething(ref a)) {}
This won't work because a is unassigned (just declared) and ref requires that you only use it with an assigned variable.
This works because a is assigned:
int a = 0;
if(TrySomething(ref a)) {}
However, in both cases (ref and out) any changes made to a within the TrySomething method are persisted to a.
As I already said, changes made to a reference type are persisted outside the method in which you make them, because through the reference, you refer to the same thing.
However, this doesn't do anything:
public void Example(SomeReferenceType s)
{
s = null;
}
Here, you just set the copy of a reference to s to null, which only exists within the scope of the method. It has zero effect on whatever you passed into the method.
If you want to do this, for whatever reason, use this:
public void Example1(ref SomeReferenceType s)
{
s = null; // Sets whatever you passed into the method to null
}
I think this covers all use-cases of out and ref.
from http://msdn.microsoft.com/en-us/vcsharp/aa336814.aspx
One way to think of out parameters is that they are like additional return values of a method. They are very convenient when a method returns more than one value, in this example firstName and lastName. Out parameters can be abused however. As a matter of good programming style if you find yourself writing a method with many out parameters then you should think about refactoring your code. One possible solution is to package all the return values into a single struct.
In contrast ref parameters are considered initially assigned by the callee. 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.
The typical use case is a method that needs to return more than one thing, so it can't just use the return value. Commonly, the return value is used for a success flag while the out parameter(s) sets values when the method is successful.
The classic example is:
public bool TryGet(
string key,
out string value
)
If it returns true, then value is set. Otherwise, it's not. This lets you write code such as:
string value;
if (!lookupDictionary.TryGet("some key", out value))
value = "default";
Note that this doesn't require you to call Contains before using an indexer, which makes it faster and cleaner. I should also add that, unlike the very similar ref modifier, the compiler won't complain if the out parameter was never initialized.
In simple words pass any variable to the function by reference so that any changes made to that variable in side that function will be persistent when function returns from execution.
Jon Skeet describes the different ways of passing parameters in great detail in this article. In short, an out parameter is a parameter that is passed uninitialized to a method. That method is then required to initialize the parameter before any possible return.
generally we cannot get the variables inside a function if we don't get by a return value.
but use keyword "out" we can change it value by a function.