What does the ref keyword actually do in C#?

Sdílet
Vložit
  • čas přidán 4. 06. 2024
  • Become a Patreon and get source code access: / nickchapsas
    Check out my courses: dometrain.com
    Hello everybody I'm Nick and in this video I am going to explain to you exactly what the ref keyword does in C#. I will explain this in the context of parameter passing because it is where you will most commonly encounter it but I will also talk about ref structs and how you can use it there to prevent something from being allocated in a place where it shouldn't.
    Timestamps
    How method parameters are passed? - 0:00
    What is ref struct? - 8:12
    ref locals, ref in methods, return ref??? - 9:31
    Don't forget to comment, like and subscribe :)
    Social Media:
    Follow me on GitHub: bit.ly/ChapsasGitHub
    Follow me on Twitter: bit.ly/ChapsasTwitter
    Connect on LinkedIn: bit.ly/ChapsasLinkedIn
    Keep coding merch: keepcoding.shop
    #csharp #dotnet #ref

Komentáře • 69

  • @minhgiangho1410
    @minhgiangho1410 Před 2 lety +70

    public interface ISerivce{}
    public interface ISerivce{}
    public interface ISerivce{}
    Please make a video on this topic

    • @nanvlad
      @nanvlad Před 2 lety +8

      it's called type variance - simple to explain but hard to understand and use in your practice

    • @tobyjacobs1310
      @tobyjacobs1310 Před 2 lety +1

      +1 for a video on these.... They're really useful if you can pick up the times you should be using them, and such a pain to get those times right...

    • @tamaratiny
      @tamaratiny Před 2 lety +2

      That wouldn't compile

    • @angelmunoz6332
      @angelmunoz6332 Před rokem

      @@tamaratiny 😂😂😂

  • @hrrrrustic
    @hrrrrustic Před 2 lety +23

    Also It could be great to mention "in" keyword for structs

  • @PaulBurg
    @PaulBurg Před 2 lety +7

    I got to this video after researching unity to help my niece out, and I have to say this just makes me appreciate C++ so much more. It manages to be much less verbose but simultaneously much more clear about what is going on.

  • @chimaokoli4943
    @chimaokoli4943 Před 2 lety +3

    Watching Nick Chapsas video > Reading Docs

  • @alphaprimal1669
    @alphaprimal1669 Před 2 lety +30

    Me here getting Pointers/Refs PTSD from my cpp era

    • @igorthelight
      @igorthelight Před 2 lety +5

      Both pointers and refs are available in C# :-)

    • @alphaprimal1669
      @alphaprimal1669 Před 2 lety +7

      well it's not called c++++ for no reason lol

  • @TomBauto
    @TomBauto Před 2 lety

    Thanks Nick good content! I liked the fact you made a correction/clarification in the end, very professional and time saver.

  • @Tolg
    @Tolg Před 2 lety +2

    Thank you so much! Learned something today. Didn’t know you could return ref values from a function!

  • @user-rm2gh2gc5f
    @user-rm2gh2gc5f Před 2 lety +3

    It's worth mentioning that you can't return a List element by reference.

  • @dyland30
    @dyland30 Před 2 lety +1

    Great content as always!

  • @rohanamada7136
    @rohanamada7136 Před 2 lety

    These videos are indeed helpful. tnx

  • @ivaniliev93
    @ivaniliev93 Před 2 lety

    readonly ref = const in C++, now we need a readonly method (which doesn't change the data members of the class) which returns a readonly ref (a reference which we can only read but not modify). I completely love these performance improvements :D

  • @art3a
    @art3a Před 2 lety +1

    Thanks for a nice video, as always! Next time, please, add a reference to a video you are talking about, would be great!

  • @spacerecluse
    @spacerecluse Před 2 lety +2

    in : arguments cannot be changed by the called method
    ref : arguments can be changed
    out : arguments must be changed by the caller and these changes are tracked in the calling context

  • @voliker
    @voliker Před 2 lety +9

    420 69 in the struct example :)
    I love you nick

  • @DarthJane
    @DarthJane Před 2 lety +1

    Another interesting case is if you have a class "class Point { public int X; public int Y; }" and then do something like:
    Point p = new Point { X = 5, Y = 10 };
    ref int x = ref p.X;
    x = 20;
    int xb = x;
    xb = 25;
    where in the end p.X is 20 and p.Y is 10, as xb creates a copy from x which is then overridden but the assignment to xb never touches p.X

  • @Bianchi77
    @Bianchi77 Před 2 lety

    Cool video, thanks :)

  • @a_i_k_0_n
    @a_i_k_0_n Před 2 lety

    Hi, thanks for your videos. Are you can to make some "off top" video? About chair, monitor rack, table? We are (programmers) spent a lot of time with this :) I'm interesting with your opinion about this topic. Thanks

  • @mohamedsalman3205
    @mohamedsalman3205 Před 2 lety +4

    What I understood is, Say the main variable is A and the parameter is B,
    Reference type without ref: Creates an object on the heap and assigns that object's location to A. So when calling the method, it is actually passing the object it self. So what happens is, It creates another allocation in the stack named B which has the pointer to the same object. Now A and B both are pointing the same object. Now when you say B equals new object, it creates a new object in the heap and updates B's location to point to the new object. Now A is pointing to the first object and B is pointing to newly created one. That's why A is not affected.
    Reference type with ref: Creates an object on the heap and assigns that object's location to A. When calling the method, it is actually passing the a reference to A or a pointer to A. So what happens is, It creates another allocation in the stack named B which has the pointer to A. It is like saying A= new object and B = A. Now when you say B equals new object, it creates a new object in the heap and since B is just a pointer to A it updates A's location to point to the new object. That's why A is affected.

    • @DarthJane
      @DarthJane Před 2 lety +1

      There is no "reference type without ref".
      You have a class, which is allocated on the heap, and you have a reference to it to access it. When passed to a method the reference is copied, but the data stays in place.
      You have a struct, which lives either inside a class, or on the stack. When passing it to a method the whole struct is copied onto the stack.
      Then you have a ref struct, the data is allocated once on the stack, and you're also given a reference to it like with a class. When passed to a method again the reference is copied, but the data again just stays in place.
      As objects on the stack are not controlled by the garbage collector accessing members of a ref struct is much more efficient than accessing members of a class.
      Then there is "passing by ref" where you have something like "myfunc(ref mytype x)", in which case a new reference is created for the method. That reference is either a reference to a reference of a class-object, or a reference to a struct, or just the copy of a reference to a ref struct. For the first case if you use new() the old reference is overridden with the reference to the new object. Any other references to the old object remain unchainged, and will still point to the old object. In the case of the latter two the actual data will be overridden.

  • @user-mb1qe8je2v
    @user-mb1qe8je2v Před 6 dny

    thanks buddy

  • @donsk324
    @donsk324 Před rokem

    I love your random values.

  • @dimitrishadrin
    @dimitrishadrin Před 2 lety +1

    One interesting point to mention in my opinion is that ref and out keywords with value type do not lead to any boxing/unboxing and it is pretty efficient in that case.

    • @nickchapsas
      @nickchapsas  Před 2 lety +1

      It’s not about just boxing but about the cost of passing a value type by reference too, which is very cheap

    • @dimitrishadrin
      @dimitrishadrin Před 2 lety +1

      @@nickchapsas this is exactly what I meant.

    • @user-cm8bn7vt9y
      @user-cm8bn7vt9y Před 2 lety

      @Nick Chapsas Hi, can you please share your settings on code visual look, what is this theme, or is it custom? Font size, font family, colors...

  • @OnsGod
    @OnsGod Před 2 lety +4

    69, 420 nice example bro

  • @woodbyte
    @woodbyte Před 2 lety +2

    Nice

  • @vertxxyz
    @vertxxyz Před 2 lety

    Is there a reason you use the VS colour scheme? To me it's kinda appalling that it doesn't have different highlighting for structs.

  • @raminquliyev2268
    @raminquliyev2268 Před 2 lety +1

    Okay Nick, Can we say that ref is same with pointer in c, c++ ?

    • @mk72v2oq
      @mk72v2oq Před 2 lety +2

      Not really, ref is like C++ reference.
      C# has actual pointers available in unsafe context.

  • @ZeroSleap
    @ZeroSleap Před rokem

    Huh never thought of this,but thats when you'd want to return a value,or just have a void function.When you pass by reference,you can ignore returning and put void.But if it's passed by value,you'd have to return the renewed value.I see.

  • @Omego2K
    @Omego2K Před 2 lety

    Ha I see what you did there. Thumbs up for that for sure

  • @benjaminclehmann
    @benjaminclehmann Před 2 lety

    Always thought that the confusing part was mixing the "ref means reference" and the "ref means stack-allocated", is there any logic behind why they both use the same keyword?

    • @DarthJane
      @DarthJane Před 2 lety

      It's not so much a mix than you think.
      As C# is managed the actual data can usually be moved freely by the garbage collector and the reference to that needs to be updated when that happens. This is what happens when you have a class. The reference is a small lightweight object that points to your actual data, which is why classes are regarded as "slow".
      Now if you take structs if you use them inside a function they are allocated on the stack, if they are part of a class the data of the instance also stores the struct (which is on the heap). Now if you do 'var mystruct = something.mystructinstance' that struct is copied onto the stack for you to use, but chaning it will not also change the struct in the original something object. Now if you want a reference to the data which is in the something object you have to use 'ref var mystruct = ref something.mystructinstance'. The issue is that this reference just isn't as fast as accessing the struct directly.
      Now for C# to be as fast as most other languages here there's the 'ref struct'. As it can only be allocated on the stack so the whole garbage collector stuff which usually runs in the background isn't active. In essence if you're using a ref struct it's allocated on the stack and you're returned a direct pointer to the object which has way faster access than a class.
      If you would try to allocate a 'ref struct' on the heap it would essentially be nothing else but a class (ignoring stuff like inheritance which structs in C# do not have to keep them as light as possible).

    • @benjaminclehmann
      @benjaminclehmann Před 2 lety

      @@DarthJane You misunderstand me. I know what the ref keyword does in both situations. I don't understand why we use the same keyword for very different things.
      Especially when constraining something to be stack allocated doesn't have anything to do with references, which is the namesake of the keyword.

  • @pramod.kulkarni9607
    @pramod.kulkarni9607 Před 9 měsíci

    Great video...

  • @carl-marvin
    @carl-marvin Před 2 lety

    I still don't know what the ref keyword in C# actually does. How is it realised? Is it just a stack pointer?

  • @siratthebox
    @siratthebox Před rokem

    Hello

  • @42069_
    @42069_ Před 2 lety

    7:48 yeah this is so random

  • @necroyzablo
    @necroyzablo Před 2 lety

    It is a pity that there were no performance tests for ref structures.

  • @weluvmusicz
    @weluvmusicz Před 2 lety +2

    Why can't we mix ref with async?

    • @DarthJane
      @DarthJane Před 2 lety +1

      async behind the scenes creates a state machine to store its data, so the "ref" you have will go out of scope.

    • @weluvmusicz
      @weluvmusicz Před 2 lety +1

      @@DarthJane Wrong: Essentially, a ref struct is not allowed to be a field of a class. Why does this matter in an async context? Because the compiler converts an async method to a class, and all local variables are turned into a field, essentially.

    • @DarthJane
      @DarthJane Před 2 lety +2

      @@weluvmusicz Depends on how you look at it. ref structs can still be used inside ref classes, but the point is that the scope of an async operation might shift, or even be on another whole thread which is why a ref class is not able to be used. So from that point of view your and my explanation are both true.

  • @olmanmora21
    @olmanmora21 Před 2 lety

    ref the way you can make an struct behave as a class

  • @meirkr
    @meirkr Před 2 lety

    Video paused. Value shall be only "hello"

  • @mascotto
    @mascotto Před 2 lety +1

    Its a basic C value and pointer..

    • @sodiboo
      @sodiboo Před 2 lety

      Not quite. C# also has pointers which is just like "basic C values and pointers", but not everyone knows C, and C# provides a similar, safer way of passing arguments by reference

    • @mascotto
      @mascotto Před 2 lety

      @@sodiboo In that case while I was watching the video, yes. Who works with C, value and pointer, masters almost everything :)
      In embedded systems, its always a rule to pass structs as pointers due low footprint and limited stack. But pointers are "wild" hehehehe

    • @protox4
      @protox4 Před 2 lety +3

      It's more like C++'s `&` reference

    • @mascotto
      @mascotto Před 2 lety

      @@protox4 Love and hate for the & and *. What else language can navigate thru structures with Ptr++ like a charm?

    • @igorthelight
      @igorthelight Před 2 lety

      @@mascotto C, C++ and C# :-)

  • @AndrewJonkers
    @AndrewJonkers Před 2 lety

    ref. The absolute worst feature of C#. Should be removed.

    • @AEF23C20
      @AEF23C20 Před 2 lety

      use sharp without refs
      thats all)

  • @tobyjacobs1310
    @tobyjacobs1310 Před 2 lety

    Ok, this one is an unusual use that you might find interesting: Improving performance when accessing members of value tuples stored in arrays.
    Given:
    class Foo
    {
    (int, int, string, string, CustomObject) _Buffer;
    ...
    public CustomObject ReadObjectAtSlow(int index) {
    (_,_,_,_,var res) = _Buffer[index];
    return res;
    }
    public CustomObject ReadObjectAtFast(int index) {
    // This should profile about 20% faster for big N scenarios
    ref var reftuple = ref _Buffer[index];
    return reftuple.Item5;
    }
    }