115

I have a object that is my in memory state of the program and also have some other worker functions that I pass the object to to modify the state. I have been passing it by ref to the worker functions. However I came across the following function.

byte[] received_s = new byte[2048];
IPEndPoint tmpIpEndPoint = new IPEndPoint(IPAddress.Any, UdpPort_msg);
EndPoint remoteEP = (tmpIpEndPoint);

int sz = soUdp_msg.ReceiveFrom(received_s, ref remoteEP); 

It confuses me because both received_s and remoteEP are returning stuff from the function. Why does remoteEP need a ref and received_s does not?

I am also a c programmer so I am having a problem getting pointers out of my head.

Edit: It looks like that objects in C# are pointers to the object under the hood. So when you pass an object to a function you can then modify the object contents through the pointer and the only thing passed to the function is the pointer to the object so the object itself is not being copied. You use ref or out if you want to be able to switch out or create a new object in the function which is like a double pointer.

Rex Logan
  • 26,248
  • 10
  • 35
  • 48

10 Answers10

240

Short answer: read my article on argument passing.

Long answer: when a reference type parameter is passed by value, only the reference is passed, not a copy of the object. This is like passing a pointer (by value) in C or C++. Changes to the value of the parameter itself won't be seen by the caller, but changes in the object which the reference points to will be seen.

When a parameter (of any kind) is passed by reference, that means that any changes to the parameter are seen by the caller - changes to the parameter are changes to the variable.

The article explains all of this in more detail, of course :)

Useful answer: you almost never need to use ref/out. It's basically a way of getting another return value, and should usually be avoided precisely because it means the method's probably trying to do too much. That's not always the case (TryParse etc are the canonical examples of reasonable use of out) but using ref/out should be a relative rarity.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 56
    I think you've got your short answer and long answer mixed up; that's a big article! – Tim Frey Mar 11 '09 at 19:44
  • 27
    @Outlaw: Yes, but the short answer itself, the directive to read the article, is only 6 words long :) – Jon Skeet Mar 11 '09 at 19:53
  • +1 all good stuff. I like to use `ref` to make it **explicit** that I expect this object to be used as a reference object, i.e. I may change something in it. Just find it makes the code more readable. – Liam Mar 21 '13 at 15:51
  • john, your link is broken – Evan Larsen Nov 25 '13 at 19:17
  • @EvanLarsen: It works for me - what happens when you try it? It should redirect to http://yoda.arachsys.com/csharp/parameters.html – Jon Skeet Nov 25 '13 at 19:17
  • Joh, this is what it shows me: Access Denied (content_filter_denied) Your request was denied because of its content categorization: "Email" For assistance, contact your network support team. – Evan Larsen Nov 25 '13 at 19:39
  • @EvanLarsen: Right - that's not the page or link being broken, that's a filter on your internet connection. Possibly a company proxy? – Jon Skeet Nov 25 '13 at 19:46
  • Yeah, I'm using companies internet so.. it probably is filtering it for some unknown reason. – Evan Larsen Nov 25 '13 at 19:52
  • 8
    @Liam Using ref like you do may see more explicit to you, but it could actually be confusing to other programmers (those who know what that keyword does anyway), because you're essentially telling potential callers, "I can modify **the variable** you used in the calling method, i.e. **reassign it to a different object (or even to null, if possible)** so don't hang on to it, or make sure you validate it when I'm done with it". That's pretty strong, and completely different from "this object can be modified", which is *always* the case anytime you pass an object reference as a parameter. – mbargiel Sep 15 '14 at 18:55
  • @JonSkeet At what scenario one should use ref? – ManirajSS Sep 18 '14 at 18:40
  • @ManirajSS: When you want those semantics, basically... which should be pretty rare, IMO. It sticks out a bit, and makes some things more painful (e.g. you have to have a variable of exactly the right type). – Jon Skeet Sep 18 '14 at 18:41
  • @ManirajSS I use it mainly to avoid returning a "new" object from helper functions (particularly when I didn't write the class being manipulated). Fewer calls to new translates into fewer garbage collections. Essentially it helps interoperability. – Matt Parkins Jun 24 '15 at 11:05
  • @JonSkeet : Excellent article. The section, "Checking you understand the preamble..." was great from a first-time reader's perspective. I did, however, find myself covering the output with my hand while reading through the sample code. Great article. – Tyler Pantuso Jan 14 '16 at 07:32
  • @JonSkeet In this age of nullable types, shouldn't `TryParse` be replacing the `out parameter` by a `nullable` type? I.e. when the parse does not succeed, `null` is returned otherwise the type. – M. Mimpen Jun 10 '16 at 06:26
  • @M.Mimpen: I think if it had been designed today, that would be the case - but now that pattern has become convention. – Jon Skeet Jun 10 '16 at 07:14
  • @M.Mimpen I don't think so regarding nullables. The Try semantic is useful for if blocks. If you had returned a nullable, you would have to assign it to a variable and check whether the variable .HasValue in the if block. Using Try, you just drop into the inner part if Try succeeds, and you can also count on your out variable being inscope and populated. – MPavlak Jul 27 '16 at 19:45
  • @MPavlak Check this: http://i.imgur.com/2ADMCCD.jpg This is way more natural if you aren't used to the Try semantic. The part of 'inscope and populated' holds for both structures. – M. Mimpen Aug 18 '16 at 06:54
  • 2
    @M.Mimpen: C# 7 will (hopefully) allow `if (int.TryParse(text, out int value)) { ... use value here ... }` – Jon Skeet Aug 18 '16 at 06:57
  • I would prefer if(int.TryParse("5") let i){ // i has the parsed value and is inscope only here } – MPavlak Aug 18 '16 at 14:35
  • @M.Mimpen How would you parse a nullable-int then? The point is that the return value of the function is whether or not it succeeded. With this approach, you would have to throw an exception to tell that the parse failed and not that it parsed to null. – MPavlak Sep 01 '16 at 14:58
  • @MPavlak I don't get your point. `int?.TryParse` doesn't exist so you have to make amends for that as well. Could you enlighten us with a real-world where you want this ability? – M. Mimpen Sep 02 '16 at 12:29
  • @M.Mimpen The point is how to tell that the function is successful vs observing the return value of the function. If I want to encode a nullable int as "null" or "1", "2", ... How to parse that back out without the Try pattern? – MPavlak Sep 05 '16 at 16:25
  • But wouldn't it be better on performance to pass a reference to a large struct than to copy the full struct, provided the struct isn't going to be modified in anyway the caller doesn't want? – AustinWBryan May 03 '18 at 14:23
  • @AustinWBryan: That's what in parameters are for in C# 7.2. But the aliasing introduces risks - if you pass in a field that way, the method could easily observe changes that it didn't expect. Yes, there can be performance benefits - but potentially at the cost of being able to reason about your code easily. – Jon Skeet May 03 '18 at 17:31
  • Honestly in my last 22 years programming of my work, I just use few times ByRef on VB.NET project. – Cheung May 23 '22 at 02:50
30

Think of a non-ref parameter as being a pointer, and a ref parameter as a double pointer. This helped me the most.

You should almost never pass values by ref. I suspect that if it wasn't for interop concerns, the .Net team would never have included it in the original specification. The OO way of dealing with most problem that ref parameters solve is to:

For multiple return values

  • Create structs that represent the multiple return values

For primitives that change in a method as the result of the method call (method has side-effects on primitive parameters)

  • Implement the method in an object as an instance method and manipulate the object's state (not the parameters) as part of the method call
  • Use the multiple return value solution and merge the return values to your state
  • Create an object that contains state that can be manipulated by a method and pass that object as the parameter, and not the primitives themselves.
Michael Meadows
  • 27,796
  • 4
  • 47
  • 63
  • 8
    Good God. I'd have to read this 20x to understand it. Sounds like a bunch of extra work to me just to do something simple. – PositiveGuy Dec 13 '10 at 19:01
  • The .NET framework does not follow your #1 rule. ('For multiple return values create structs'). Take for example `IPAddress.TryParse(string, out IPAddress)`. – Swen Kooij Dec 06 '13 at 21:47
  • @SwenKooij You're right. I'm assuming that in most places where they use out parameters it either (a) They are wrapping a Win32 API, or (b) it was early days, and the C++ programmers were making decisions. – Michael Meadows Dec 11 '14 at 18:36
  • 1
    @SwenKooij I know this reply is many years late, but it does. We're used to TryParse, but it doesn't mean it's good. It would have been better if rather than `if (int.TryParse("123", out var theInt) { /* use theInt */ }` we had `var candidate = int.TrialParse("123"); if (candidate.Parsed) { /* do something with candidate.Value */ }` It is more code, but is much more consistent with the C# language design. – Michael Meadows Jul 01 '18 at 22:02
15

You could probably write an entire C# app and never pass any objects/structs by ref.

I had a professor who told me this:

The only place you'd use refs is where you either:

  1. Want to pass a large object (ie, the objects/struct has objects/structs inside it to multiple levels) and copying it would be expensive and
  2. You are calling a Framework, Windows API or other API that requires it.

Don't do it just because you can. You can get bit in the ass by some nasty bugs if you start changing the values in a param and aren't paying attention.

I agree with his advice, and in my five plus years since school, I've never had a need for it outside of calling the Framework or Windows API.

sdgfsdh
  • 33,689
  • 26
  • 132
  • 245
Chris
  • 6,702
  • 8
  • 44
  • 60
  • 5
    If you plan to implement "Swap", passing by ref could be helpful. – Brian Mar 11 '09 at 21:37
  • @Chris will it make any problem if i use ref keyword for small objects? – ManirajSS Sep 18 '14 at 18:43
  • @TechnikEmpire "But, alterations to the object within the scope of the called function are not reflected back to the caller." That is wrong. If I pass a Person to `SetName(person, "John Doe")`, the name property will change and that change will be reflected to the caller. – M. Mimpen Jun 10 '16 at 07:37
  • @M.Mimpen Comment deleted. I had barely picked up C# at that point and was clearly talking out my *$$. Thanks for bringing it to my attention. –  Jun 10 '16 at 07:40
  • 2
    @Chris - I'm pretty sure passing a "large" object isn't expensive. If you just pass it by value you are still just passing a single pointer right? – Ian Jun 22 '17 at 23:20
3

Since received_s is an array, you're passing a pointer to that array. The function manipulates that existing data in place, not changing the underlying location or pointer. The ref keyword signifies that you're passing the actual pointer to the location and updating that pointer in the outside function, so the value in the outside function will change.

E.g. the byte array is a pointer to the same memory before and after, the memory has just been updated.

The Endpoint reference is actually updating the pointer to the Endpoint in the outside function to a new instance generated inside the function.

Chris Hynes
  • 9,999
  • 2
  • 44
  • 54
3

Think of a ref as meaning you are passing a pointer by reference. Not using a ref means you are passing a pointer by value.

Better yet, ignore what I just said (it's probably misleading, especially with value types) and read This MSDN page.

Brian
  • 25,523
  • 18
  • 82
  • 173
  • Actually, not true. At least the second part. Any reference type will always be passed by reference, whether you use ref or not. – Erik Funkenbusch Mar 11 '09 at 20:28
  • Actually, on further reflection, that didn't come out right. The reference is actually passed by value without the ref type. Meaning, changing the values pointed at by the reference changes the original data, but changing the reference itself does not change the original reference. – Erik Funkenbusch Mar 11 '09 at 20:43
  • 2
    A non-ref reference type is not passed by reference. A reference to the reference type is passed by value. But if you want to think of a reference as a pointer to something that is being referenced, what I said makes sense (but thinking that way may be misleading). Hence my warning. – Brian Mar 11 '09 at 21:36
  • Link is dead - try this one instead - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref – GIVE-ME-CHICKEN Sep 10 '19 at 07:16
1

While I agree with Jon Skeet's answer overall and some of the other answers, there is a use case for using ref, and that is for tightening up performance optimizations. It has been observed during performance profiling that setting the return value of a method has slight performance implications, whereas using ref as an argument whereby the return value is populated into that parameter results in this slight bottleneck being removed.

This is really only useful where optimization efforts are taken to extreme levels, sacrificing readability and perhaps testability and maintainability for saving milliseconds or perhaps split-milliseconds.

Jon Davis
  • 6,562
  • 5
  • 43
  • 60
0

When You pass an value type as an argument to a method (for example method named 'ChangeAge()') with ref keyword , then the changes made to the value type in the 'ChangeAge()' method will also get reflected back to the value in the calling method .

So , The Main Purpose of 'ref' keyword is to modify the value of an value type that is passed as an argument to a method . By Default , C# passes argument as values .

class PassByReferenceExample

{
    static void Main(string[] args)
     
    {
      
       int age = 12 ;
       Console.WriteLine(age) ;
       
       ChangeName(ref age);

       //printing the name after changing the value by passing the 
       //reference
       
       //Now the Name will be changed from "Alex" to "Adam"

       Console.WriteLine(age);

     }

     static void ChangeAge(ref int age)

     {
        age = 20 ;

     }

  }
 

So, In the above example when a value type (int) 'age' is passed as an argument to 'ChangeAge()' method with 'ref' keyword , the changes made to the 'age' in the 'ChangeAge()' method will also get reflected back in the calling method .

-1

Ground zero rule first, Primitives are passed by value(stack) and Non-Primitive by reference(Heap) in the context of TYPES involved.

Parameters involved are passed by Value by default. Good post which explain things in details. http://yoda.arachsys.com/csharp/parameters.html

Student myStudent = new Student {Name="A",RollNo=1};

ChangeName(myStudent);

static void ChangeName(Student s1)
{
  s1.Name = "Z"; // myStudent.Name will also change from A to Z
                // {AS s1 and myStudent both refers to same Heap(Memory)
                //Student being the non-Primitive type
}

ChangeNameVersion2(ref myStudent);
static void ChangeNameVersion2(ref Student s1)
{
  s1.Name = "Z"; // Not any difference {same as **ChangeName**}
}

static void ChangeNameVersion3(ref Student s1)
{
    s1 = new Student{Name="Champ"};

    // reference(myStudent) will also point toward this new Object having new memory
    // previous mystudent memory will be released as it is not pointed by any object
}

We can say(with warning) Non-primitive types are nothing but Pointers And when we pass them by ref we can say we are passing Double Pointer

Community
  • 1
  • 1
  • *All* parameters are passed by value, by default, in C#. *Any* parameter can be passed by reference. For reference types, the value that is passed (either by reference or by value) is itself a reference. That is entirely independent of how it is passed. – Servy Apr 14 '14 at 16:22
  • Agree @Servy ! "When we hear the words "reference" or "value" used we should be very clear in mind whether we meant that a parameter is a reference or value parameter, or whether we mean that the type involved is a reference or value type' Little Confusion out there on my side, WHen i said _Ground zero rule first, Primitives are passed by value(stack) and Non-Primitive by reference(Heap)_ I meant from TYPES involved, Not the Parameter ! When we talk about Parameters You are Correct, All parameters are passed by value,by default in C# . – Surender Singh Malik Apr 14 '14 at 16:29
  • Saying that a parameter is a reference or value parameter is not a standard term, and is really ambiguous as to what you mean. The type of the parameter can either be a reference type or a value type. Any parameter can be passed by value or by reference. These are orthogonal concepts for any given parameter. Your post incorrectly describes this. – Servy Apr 14 '14 at 16:32
  • Sorry ,I'll disagree on this @Servy ! By ref(Heap) or By val(Stack) are just standard keywords to describe the nature of the Variables. It doesn't matter whether the Variable involved is a Parameter Variable or Normal variable. – Surender Singh Malik Apr 14 '14 at 16:37
  • Passing a parameter by reference has *nothing* to do with the heap. The heap isn't even *used* when passing a parameter by reference. The stack alone is used for such an operation, as is the case when a parameter is passed by value. The difference is merely whether the variable has its own stack space allocated, or if all uses of the parameter's identifier correspond with some existing location in the stack instead. – Servy Apr 14 '14 at 16:48
  • If we are calling a function STACK is the only thing which is being used,But Variables in stack can always refer to HEAP. In C#, vari­ables are stored in either the Stack or the Heap based on their type: Val­ues types go on the stack Ref­er­ence types go on the heap struct in C# is a value type like enum, so both go on the stack i.e rec­om­mended (for bet­ter per­for­mance) that you pre­fer a struct type to a ref­er­ence type for small objects which are mainly used for stor­ing data. for more details :http://theburningmonk.com/2010/02/the-stack-the-heap-and-the-memory-pitfalls/ – Surender Singh Malik Apr 14 '14 at 16:56
  • That is just full of wrongness. First off, as I said before, this is all *entirely irrelevant* when discussing whether a particular parameter is passed by reference or by value. Additionally, value types do not necessarily go on the stack. Your determination as to whether to use a value or reference type is also quite poor. You should use a value type *when the type you are representing conceptually represents a single value*. Dealing with value types is also hard to understand for most newer users (clearly including you) and so should generally be avoided until they are well understood. – Servy Apr 14 '14 at 16:59
  • The article you're quoting is just full of wrong/misleading/generally bad content. You should not trust or rely on anything it says. – Servy Apr 14 '14 at 17:01
  • Roger ! But when someone like Jeffrey Richter says you have to believe. http://msdn.microsoft.com/en-us/magazine/cc301569.aspx – Surender Singh Malik Apr 14 '14 at 17:12
  • I guess we are thinking from different perspective. I am talking about By ref & by Val in the context of TYPES. You are focusing on Parameters. Whatever you pass to a function ultimately gets pushed to the stack. Now it depend on how one has passed it and What has been passed. – Surender Singh Malik Apr 14 '14 at 17:16
  • But your answer and comments are not in line with the content of that article. I didn't read through the whole thing, but it looks to be a decent article. If you *accuracy* represented those points, *then* you could potentially have a good post. – Servy Apr 14 '14 at 17:17
  • 1
    You pass parameters by reference or by value. The terms "by reference" and "by value" are not used to describe whether a type is a value type or a reference type. – Servy Apr 14 '14 at 17:18
  • It can be the case, As i am quite sleepy now ! You nailed it down for me too ! "Ref" or "value" and "by ref" or "by value" are used in different context. 'by' being used in Parameter and the other in TYPE ! And when it comes to concept it depend on lots of things (they way you paint the picture of computer and other ) – Surender Singh Malik Apr 14 '14 at 17:20
  • You have made a number of statements that are flat wrong, and provably so. In many cases you have used the improper terminology to refer to particular concepts; this results in statements that are at worst, strictly wrong, and at best, highly misleading. Virtually nothing you've said here accurately describes the concepts you are claiming they describe. – Servy Apr 14 '14 at 17:23
  • Nopes ! It's just the matter of perception. I was talking from Types perspective. – Surender Singh Malik Apr 14 '14 at 17:42
  • 1
    No, it's *not* a matter of perception. When you use the *incorrect term* to refer to something then that statement becomes *wrong*. It is important for correct statements to use the correct terminology to refer to concepts. – Servy Apr 14 '14 at 17:47
-1

I know this question is old, but I would to brief the answer for any new curious newbie developers.

Try as much as you can to avoid using ref/out, it is against writing a clean code and bad quality code.

Passing types by reference (using out or ref) requires experience with pointers, understanding how value types and reference types differ and handling methods that have multiple return values. Also, the difference between out and ref parameters is not widely understood.

please check

https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1045

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 19 '23 at 08:54
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/33861847) – Fogh Feb 21 '23 at 13:19
  • thanks for your help and clarification, I will consider this point in the next post, But what I shall do now? I cannot post any new comments anymore! shall I delete the above answer? – Mohammed Jawad Feb 21 '23 at 14:18
-1

my understanding is that all objects derived from Object class are passed as pointers whereas ordinary types (int, struct) are not passed as pointers and require ref. I am nor sure about string (is it ultimately derived from Object class ?)

Lucas
  • 1
  • This could use some clarification. What's the diffrence between value- and reference tyoes. Ans why is that relevant to using the ref keyword on a parameter? – oɔɯǝɹ Oct 28 '12 at 23:53
  • In .net, everything except pointers, type parameters and interfaces is derived from Object. It is important to understand, that "ordinary" types (correctly called "value types") inherit from object, too. You are right from that on: Value types (per default)are passed by value, whereas reference types are passed by reference. If you wanted to modify a value type, rather than returning a new one (handle it like a reference type inside a method), you would have to use the ref keyword on it. But that is bad style and you just should not do that unless you are absolutely sure that you have to :) – buddybubble Jan 16 '13 at 21:16
  • 1
    to answer your question: string is derived from object.It is a reference type that behaves like a value type (for performance and logical reasons) – buddybubble Jan 16 '13 at 21:19