C# ref is it like a pointer in C/C++ or a reference in C++?

前端 未结 6 455
悲&欢浪女
悲&欢浪女 2021-01-30 00:10

I\'m working with the ref and don\'t understand clearly \"Is it like a pointer as in C/C++ or it\'s like a reference in C++?\"

Why did I ask such a

6条回答
  •  花落未央
    2021-01-30 00:39

    In C#, when you see something referring to a reference type (that is, a type declared with class instead of struct), then you're essentially always dealing with the object through a pointer. In C++, everything is a value type by default, whereas in C# everything is a reference type by default.

    When you say "ref" in the C# parameter list, what you're really saying is more like a "pointer to a pointer." You're saying that, in the method, that you want to replace not the contents of the object, but the reference to the object itself, in the code calling your method.

    Unless that is your intent, then you should just pass the reference type directly; in C#, passing reference types around is cheap (akin to passing a reference in C++).

    Learn/understand the difference between value types and reference types in C#. They're a major concept in that language and things are going to be really confusing if you try to think using the C++ object model in C# land.

    The following are essentially semantically equivalent programs:

    #include 
    
    class AClass
    {
        int anInteger;
    public:
        AClass(int integer)
            : anInteger(integer)
        {  }
    
        int GetInteger() const
        {
            return anInteger;
        }
    
        void SetInteger(int toSet)
        {
            anInteger = toSet;
        }
    };
    
    struct StaticFunctions
    {
        // C# doesn't have free functions, so I'll do similar in C++
        // Note that in real code you'd use a free function for this.
    
        static void FunctionTakingAReference(AClass *item)
        {
            item->SetInteger(4);
        }
    
        static void FunctionTakingAReferenceToAReference(AClass **item)
        {
            *item = new AClass(1729);
        }
    };
    
    int main()
    {
        AClass* instanceOne = new AClass(6);
        StaticFunctions::FunctionTakingAReference(instanceOne);
        std::cout << instanceOne->GetInteger() << "\n";
    
        AClass* instanceTwo;
        StaticFunctions::FunctionTakingAReferenceToAReference(&instanceTwo);
        // Note that operator& behaves similar to the C# keyword "ref" at the call site.
        std::cout << instanceTwo->GetInteger() << "\n";
    
        // (Of course in real C++ you're using std::shared_ptr and std::unique_ptr instead,
        //  right? :) )
        delete instanceOne;
        delete instanceTwo;
    }
    

    And for C#:

    using System;
    
    internal class AClass
    {
        public AClass(int integer)
            : Integer(integer)
        {  }
    
        int Integer { get; set; }
    }
    
    internal static class StaticFunctions
    {
        public static void FunctionTakingAReference(AClass item)
        {
            item.Integer = 4;
        }
    
        public static void FunctionTakingAReferenceToAReference(ref AClass item)
        {
            item = new AClass(1729);
        }
    }
    
    public static class Program
    {
        public static void main()
        {
            AClass instanceOne = new AClass(6);
            StaticFunctions.FunctionTakingAReference(instanceOne);
            Console.WriteLine(instanceOne.Integer);
    
            AClass instanceTwo  = new AClass(1234); // C# forces me to assign this before
                                                    // it can be passed. Use "out" instead of
                                                    // "ref" and that requirement goes away.
            StaticFunctions.FunctionTakingAReferenceToAReference(ref instanceTwo);
            Console.WriteLine(instanceTwo.Integer);
        }
    }
    

提交回复
热议问题