• ref


    Why use the 'ref' keyword when passing an object?

    Pass a ref if you want to change what the object is:

    TestRef t = new TestRef();
    t.Something = "Foo";
    DoSomething(ref t);
    
    void DoSomething(ref TestRef t)
    {
      t = new TestRef();
      t.Something = "Not just a changed t, but a completely different TestRef object";
    }

    After calling DoSomething, t does not refer to the original new TestRef, but refers to a completely different object.

    This may be useful too if you want to change the value of an immutable object, e.g. a string. You cannot change the value of a string once it has been created. But by using a ref, you could create a function that changes the string for another one that has a different value.

    Edit: As other people have mentioned. It is not a good idea to use ref unless it is needed. Using ref gives the method freedom to change the argument for something else, callers of the method will need to be coded to ensure they handle this possibility.

    Also, when the parameter type is an object, then object variables always act as references to the object.

    This means that when the ref keyword is used you've got a reference to a reference.

    This allows you to do things as described in the example given above.

    But, when the parameter type is a primitive value (e.g. int),

    then if this parameter is assigned to within the method,

    the value of the argument that was passed in will be changed after the method returns:

    int x = 1;
    Change(ref x);
    Debug.Assert(x == 5);
    WillNotChange(x);
    Debug.Assert(x == 5); // Note: x doesn't become 10
    
    void Change(ref int x)
    {
      x = 5;
    }
    
    void WillNotChange(int x)
    {
      x = 10;
    }

    引用类型 

    对于引用类型的参数而言,传参进去之后,可以改变参数所指向的对象。所以只对immutable的引用类型有意义,普通的引用类型,本身就具有改变参数指向的对象的功能。

    比如string的使用,虽然在方法内部设置了,但是出了方法后,并没有设置成功

    String是被特殊处理过的引用类型,在函数内部处理过的话不会带到函数外部,通过使用ref string类型的参数,可以实现函数内部修改了参数,函数外部也会变化

     public void ToLower(string str)
        {
            str = str.ToUpper();
        }

     https://stackoverflow.com/questions/1096449/c-sharp-string-reference-type

    值类型

    对于值类型的参数而言,如果在传参进去的方法内部改变的值类型参数的值,那么在方法返回之后,对应的值类型参数的数值是会被改变的。

    ref (C# Reference)

    Passing an argument by reference

    When used in a method's parameter list, the ref keyword indicates that an argument is passed by reference, not by value. The ref keyword makes the formal parameter an alias for the argument, which must be a variable. In other words, any operation on the parameter is made on the argument. For example, if the caller passes a local variable expression or an array element access expression, and the called method replaces the object to which the ref parameter refers, then the caller's local variable or the array element now refers to the new object when the method returns.

     Note

    Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same.

    A method parameter can be modified by ref regardless of whether it is a value type or a reference type.

    There is no boxing of a value type when it is passed by reference.

    When to use ref and when it is not necessary in C#

    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.

    How are strings passed in .NET?

    To answer your question, consider the following code:

    void Main()
    {
        string strMain = "main";
        DoSomething(strMain);
        Console.Write(strMain); // What gets printed?
    }
    void DoSomething(string strLocal)
    {
        strLocal = "local";
    }

    There are three things you need to know in order to predict what will happen here, and to understand why it does.

    1. Strings are reference types in C#. But this is only part of the picture.
    2. They are also immutable, so any time you do something that looks like you're changing the string, you aren't. A completely new string gets created, the reference is pointed at it, and the old one gets thrown away.
    3. Even though strings are reference types, strMain isn't passed by reference. It's a reference type, but the reference is being passed by value. This is a tricky distinction, but it's a crucial one. Any time you pass a parameter without the ref keyword (not counting out parameters), you've passed something by value.

    But what does that mean?

    Passing reference types by value: You're already doing it

    There are two groups of data types in C#: reference types and value types. There are also two ways to pass parameters in C#: by reference and by value. These sound the same and are easily confused. They are NOT the same thing!

    If you pass a parameter of ANY type, and you don't use the ref keyword, then you've passed it by value. If you've passed it by value, what you really passed was a copy.

    But if the parameter was a reference type, then the thing you copied was the reference, not whatever it was pointing at.

    Here's the first line of our Main method:

    string strMain = "main";

    There are actually two things we've created on this line: a string with the value main stored off in memory somewhere, and a reference variable called strMain pointing to it.

    DoSomething(strMain);

    Now we pass that reference to DoSomething. We've passed it by value, so that means we made a copy. But it's a reference type, so that means we copied the reference, not the string itself. Now we have two references that each point to the same value in memory.

    Inside the callee

    Here's the top of the DoSomething method:

    void DoSomething(string strLocal)

    No ref keyword, as usual. So strLocal isn't strMain, but they both point to the same place. If we "change" strLocal, like this...

    strLocal = "local";

    ...we haven't changed the stored value, per se. We've re-pointed the reference. We took the reference called strLocal and aimed it at a brand new string. What happens to strMain when we do that? Nothing. It's still pointing at the old string!

    string strMain = "main"; //Store a string, create a reference to it
    DoSomething(strMain);    //Reference gets copied, copy gets re-pointed
    Console.Write(strMain);  //The original string is still "main" 

    Immutability is important

    Let's change the scenario for a second. Imagine we aren't working with strings, but some mutable reference type, like a class you've created.

    class MutableThing
    {
        public int ChangeMe { get; set; }
    }

    If you follow the reference objLocal to the object it points to, you can change its properties:

    void DoSomething(MutableThing objLocal)
    {
         objLocal.ChangeMe = 0;
    }

    There's still only one MutableThing in memory, and both the copied reference and the original reference still point to it. The properties of the MutableThing itself have changed:

    void Main()
    {
        var objMain = new MutableThing();
        objMain.ChangeMe = 5; 
        Console.Write(objMain.ChangeMe);  //it's 5 on objMain
    
        DoSomething(objMain);             //now it's 0 on objLocal
        Console.Write(objMain.ChangeMe);  //it's also 0 on objMain   
    }

    Ah, but...

    ...strings are immutable! There's no ChangeMe property to set. You can't do strLocal[3] = 'H'; like you could with a C-style char array; you have to construct a whole new string instead. The only way to change strLocal is to point the reference at another string, and that means nothing you do to strLocal can affect strMain. The value is immutable, and the reference is a copy.

    So even though strings are reference types, passing them by value means whatever goes on in the callee won't affect the string in the caller. But since they are reference types, you don't have to copy the entire string in memory when you want to pass it around.

    Further resources:

              

  • 相关阅读:
    使用Samba或NFS实现文件共享
    Web架构学习
    使用Postfix与Dovecot部署邮件系统
    使用Bind提供域名解析服务
    使用PXE+Kickstart无人值守安装服务
    初识MariaDB数据库管理系统
    使用DHCP动态管理主机地址
    使用Vsftpd服务传输文件
    使用iSCSI服务部署网络存储
    使用Squid部署代理缓存服务
  • 原文地址:https://www.cnblogs.com/chucklu/p/7477058.html
Copyright © 2020-2023  润新知