what is use of out parameter in c#

后端 未结 9 1168
南方客
南方客 2021-02-07 16:27

Can you please tell me what is the exact use of out parameter?

Related Question:
What is the differen

9条回答
  •  孤街浪徒
    2021-02-07 16:41

    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.

提交回复
热议问题