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 _);
Related
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.
Here's the syntax for using TryParse
int a;
bool success = Int32.TryParse("0",out a);
But how on earth could this work? The variable a hasn't been instantiated!
An out parameter does not need to be instantiated in the calling method. In fact, any value it had in the calling method would be overwritten by the called method.
Example:
public static bool MyTryParse(string value, out int result){
int hold;
if (int.TryParse(value, out hold)){
result = hold;
return true;
}
// Comment out the following line and you'll get a compile error
result = default(int); // This method MUST set result
return false;
}
As you can see, even if the caller set some value on the parameter, that value will be overwritten.
Further, note that this works in exactly the same way if a reference type is used.
From "out (C# Reference)":
The out keyword causes arguments to be passed by reference.
...
Although variables passed as out arguments do not have to be initialized before being passed, the called method is required to assign a value before the method returns.
...
something I didn't know:
Overloading can be done, however, if one method takes a ref or out argument and the other uses neither, like this:
class OutOverloadExample
{
public void SampleMethod(int i) { }
public void SampleMethod(out int i) { i = 5; }
}
The semantics of an out parameter are that the variable does not need to be assigned previously when calling the method. The compiler marks the variable as "definitely assigned", in the parlance of the C# spec, which means it is legal to use in later expressions because it must have been initialized with a value inside the method.
This is rule is stated in section 5.1.6 of the C# specification:
A variable need not be definitely assigned before it can be passed as an output parameter in a function member or delegate invocation.
This is different from a ref parameter which the must be definitely assigned before being passed to a method but the method will be able to modify the variable.
What you are doing using the out keyword is passing by reference your a. Look at the generated IL:
if you see at line IL_0006 there is an instruction called ldloca.s:
Loads the address of the local variable at a specific index onto the evaluation stack, short form.
To summarize: out causes the argument to be passed by reference so when you pass your variable to TryParse, to the variable a is assigned the value of the string your passing once it has been converted.
hope it helps.
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
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.
Something like:
if the value of the variable after the method call has to be returned :
if can be instantiated before the method call use ref
if does not need to be instantiated before the call use out
if the value of the variable is used for returning , deciding or calculating other values from the method call do not use ref neither out
Did I get it correctly ? What is your short guideline ?
For value types :
If you just want to use the value contained AND NOT alter it in the original place use the default passing method (by value)
If you need to alter it in the original store, use ref. Example :
int a = -3;
protected void EnsurePositiveValues(ref int value)
{
if (value < 0)
value = 0;
}
For reference types :
If you need to just use the instance or alter it use the default passing method (by reference ; should be called "by reference copy")
If you need to (re)assign in the original reference then use ref. Example :
User u = MembershipAPI.GetUser(312354);
protected void EnsureUser(ref User user)
{
if (user == null)
user = new User();
}
You also need to take into account value and reference types. When passing a reference type to a method as a parameter, you pass the pointer to the variable. This means that inside the method you can make changes to the variable and they will be available to the code that called the method, however if you set it to null, you are only setting the pointer to null and the variable will be intact when your method returns.
Not sure if this is really answering your question but one good usage of passing a value by ref (using the out keyword) I have found is...
int i = 0;
if (int.TryParse("StringRepresentation", out i)
{
// do something with i which has taken the value of a the previous successful TryParse
}