-2

I was sticking on Unity for a while, without knowing much about Computer Science/Performance management.

Now, I took some C++ experience, with some concerns on IO/performance/etc some "Computer Engineering" stuffs.

Then I got back to my old Unity project, which had no concern about those thing at all, and found out that there is ref(or out) keyword for call-by-reference, as I could do in my C++ project.

Is it common to use ref(for call-by-reference purpose) of C# on 'business level'?(maybe game companies with Unity?)

Cardstdani
  • 4,999
  • 3
  • 12
  • 31
TechBlast
  • 61
  • 1
  • 6
  • https://stackoverflow.com/questions/20450888/using-ref-in-c-sharp according to a comment on this page, it's not common; which would be right? – TechBlast Jul 23 '20 at 06:56
  • Do you know the difference between a value and a reference type? Most things you pass in C# are *already* passed *as a reference* under the hood. – nvoigt Jul 23 '20 at 06:56
  • I supposed its how you look at it. every single C# feature is common and used extensively. I guess at this stage you should probably do some research on those particular language features – TheGeneral Jul 23 '20 at 07:01
  • `Is it common to use ref` .. well for some reason it exists ;) Completely depends on the use case .. note that all class (reference) types are passed by reference anyway so the ref only makes a difference for structs (value types).... – derHugo Jul 23 '20 at 07:08
  • Does this answer your question? [What's the difference between the 'ref' and 'out' keywords?](https://stackoverflow.com/questions/388464/whats-the-difference-between-the-ref-and-out-keywords) – keco Jul 23 '20 at 07:10
  • @keco I don't think the question is about what is the difference but rather what it is used for at all – derHugo Jul 23 '20 at 07:11
  • @derHugo If you understand the differences you know when to use it (more likely). – keco Jul 23 '20 at 07:13
  • @keco That question is about the difference (which this is not) and conveys a completely wrong picture in the context of this question. If I had this question and read your linked answer, I would take away that it works just like in C++ and I had to do it with every function call, because nothing in the linked question explains the difference between C++ and C#. – nvoigt Jul 23 '20 at 07:13
  • @keco the given answers there only explain the difference from a pure c# perspective so you will only understand the difference if you already know their general purpose ... They are also not really helpful actually. `ref` you only want/have to use on structs and value types while `out` can be used for both anytime you simply want a method to return more then one type .. – derHugo Jul 23 '20 at 07:16

1 Answers1

3

If you come from C++ then you have this thought in your head that you need to pass references, because if you don't, the whole object will be copied and most likely that is bad (tm).

In C#, types are either reference types or value types. Reference types are passed by reference automatically. If you pass a class, it can be null, so it must already be a reference to the actual class instance (or in C++ terminology a "pointer", because references in c++ cannot be null).

All classes are reference types. You don't need ref or out for performance reasons ever. If you find yourself using ref or out for performance reasons on a struct, that should be your clue that it should be a class instead.

So no, using ref or out is not common in C# at all. It is only used sparingly, in the places where you would not get the desired result without it. Those keywords are not meant for performance considerations.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • I use it on numeric values or structs I have no access to so I can't convert them to classes e.g. – derHugo Jul 23 '20 at 07:14
  • 1
    The whole point of a struct is that it is so small, that *copying it* is *faster* than the indirection via reference. If those structs come from a source you trust to make good software decisions, use them without ref/out. If you don't trust the source to make good software decisions, pick another source. – nvoigt Jul 23 '20 at 07:17
  • "Reference types are passed by reference automatically." Actually, that's not entirely accurate. Reference types are not passed at all - what's being passed is the reference itself, and it's being passed by value. For more information, [read this.](https://jonskeet.uk/csharp/parameters.html) – Zohar Peled Jul 23 '20 at 07:25
  • I may have musunderstood the point of `ref` and `out`, but I thought they're not about performance or "having to copy the whole struct", but more about being able to change/set the value of a variable "outside" its original scope. So of course you could have a method `int AddOne(int value) => value + 1;` and use it like `int i = 1; i = AddOne(i);`. But you could also do it like `void AddOne(ref int value) => value += 1;` and use it like `int i = 1; AddOne(ref i);` in a more involved scenario, the latter could be more readable. And I like `out` very much in `TryParse` or `TryGet` situations. – Corak Jul 23 '20 at 07:27
  • @ZoharPeled I think it is clear that nvoigt means exactly that ;) – derHugo Jul 23 '20 at 07:28
  • @derHugo Though it might be clear to you, I think many beginners find that very confusing. I've seen my share of questions in SO and other places that wouldn't have been asked at all if the OP would have a better understanding on reference types vs value types and particularly about how they behave when being passed into methods. My point is, if reference types would have been passed by reference, a method like `void DoThings(ref string arg) {}` shouldn't compile. The fact that it does compile should be the first hint as to why reference types are *not* passed by reference automatically. – Zohar Peled Jul 23 '20 at 07:34
  • @ZoharPeled I think `string` is a tricky example because it is a special case in c# ;) e.g. https://stackoverflow.com/questions/10792603/how-are-strings-passed-in-net – derHugo Jul 23 '20 at 07:40
  • @derHugo You're missing the point. Don't use `string`, use anything that's a reference type - the point still stands with `void DoThings(ref object arg) {}`. – Zohar Peled Jul 23 '20 at 07:43
  • @Corak That is what I meant by "in the places you would not get the desired result without it". – nvoigt Jul 23 '20 at 07:44
  • @ZoharPeled `ref object arg` is passing the **reference** *by reference*. In C++ that would be a double pointer (`type** name`). `object arg` is absolutely sufficient to call methods on `arg` that change properties of arg. Clear evidence of having passed `arg` by reference instead of by-value. – nvoigt Jul 23 '20 at 07:46
  • @nvoigt `DoSomething(object arg)` and `DoSomething(ref object arg)` are two different methods. Why? because in the first method, the reference is being passed by value, while in the second method, the reference passed into the method is used from inside the method itself. If Jon Skeet's article didn't convince you there's a difference, perhaps [this little demo](https://rextester.com/CJXTD30925) will. – Zohar Peled Jul 23 '20 at 08:00
  • @ZoharPeled I know that. Do you know enough C++ to draw the parallels? You don't seem to understand what I'm saying. `object arg` is passing `arg` "by reference", simply because `object` is a reference type in C#, a distinction that does not exist in C++. `ref object arg` is passing the *reference* "by reference", so a double indirection, in C++ known as "object** arg". – nvoigt Jul 23 '20 at 08:09
  • @nvoigt I don't know C++, but I do know enough about C#, and IMHO, using the terminology of one language to describe what's going on in another language is wrong. I believe what you wrote about C++, however I think that parallel you're drawing is confusing because you're applying C++ terminology on C#, which is wrong. In c#, everything is passed by value unless being passed as a ref or out, regardless of the question if the parameter is a reference or value type. That's the point I'm trying to make. – Zohar Peled Jul 23 '20 at 08:15
  • @ZoharPeled I'm afraid you are wrong in the terminology you use then. "f(Button b)" is passing the button by-reference. You could be nitpicky and say "actually, it's passing the button reference by-value", but guess what? That is *exactly* what "by reference" means. "by value" and "by reference" are not C# terms. the are general computing terms. If a reference is passed, then it's "by reference". And in C# a reference *is* passed, because that is what "Button" *is* assuming it's a reference type. Saying "f(Button b)" is passing the button instance by value is just plain wrong. – nvoigt Jul 23 '20 at 08:28
  • 1
    @nvoigt Ok, I'll accept that explanation. – Zohar Peled Jul 23 '20 at 09:02