CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Apr 2012
    Posts
    13

    Pointer Workaround

    I'm coming to C# with some experience in C++.

    Suppose I have the following


    class Area
    {
    Foo someObject;
    }

    class Ship
    {
    Area currentLocation;

    }


    static void Main()
    {
    Ship theShip = new Ship();
    Area theArea = new Area();

    theShip.currentLocation = theArea;
    //Now I have some function, to which the ship is passed

    doSomething(theShip);

    }

    //Function definition
    void doSomething(Ship ship)
    {
    Foo newObject;
    ship.currentLocation.someObject = newObject;

    }



    Is there a convenient way to link the currentLocation object in the ship class to the instance of theArea defined in main? In C++ I would have just stored currentLocation as a pointer to do this. I need to be able to pass the theShip object to a function and have that function modify the properties of the Area associated with the ship.

    My current implementation uses a list of Area objects which each have an ID, and I store the ID in the currentLocation variable and use a Dictionary to lookup the index of the Area object so that I can go back and access the list. This all seems terribly inefficient.

  2. #2
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Pointer Workaround

    C# has a different type system than the one you're used to in C++: C# makes a distinction between value types (structs), and reference types (classes).

    In essence, variables of value types store their values directly, while variables of reference types store a reference to the actual object. Note that the concept of "reference" here is not the same as the concept of a C++ reference: C# references are an internal implementation detail, not directly exposed to the language, and are subject to garbage collection - so they are kinda like smart pointers. You can manipulate them, though, via reference types.

    Now, you'll often find definitions emphasizing that value types are allocated on the stack, while reference types are allocated on the heap - however, this is not the core distinction between them. There is no requirement for this, and the statement is specific to Microsoft's implementation of the CLR, to improve performance. Furthermore, it is not always the case: there are situations that can result on value types being allocated on the heap (see this article.)

    What is important to understand is how these two type families behave when passed to a method. Value types are passed by value - as you would expect by the name. Reference types are, you guessed it, passed by reference (more precisely, the internal reference is passed by value, but since it's pointing to the same memory location, the object itself is passed by reference).
    The bottom line is: in C#, you almost never need C++-like pointers, since reference types can do the job for you. Furthermore, you might be surprised that there are pointers in C#, but the rules for using them are more strict (for example, they must be used inside code blocks designated with the unsafe keyword - a somewhat misleading keyword, since it's not "unsafe" if you know what you're doing ), but as I already said, in C# programming, you'll almost never (or even never) need to use them.
    (Note, there is also a way to pass value types by reference, but that's off-topic; you can look up the ref keyword.)

    So, for what you want to do, having a reference type field will suffice: the solution is pretty much exactly like the code you posted, with a few minor details that need to be addressed (BTW: please use the [code][/code] tags when posting code).

    Just like in C++, you can (and should) use access modifiers in you classes. While in C++ you apply them to a group of members, in C# you designate each member separately. If you don't do it, the member will have the default access modifier, which is private - so you won't be able to access the given member from outside the class.

    However, in the spirit of good OO design, you don't want to publicly expose member fields; while in C++ you'd create a getter and a setter method, the C# language provides you with properties specifically for that purpose (they are really just syntactic suggar for a getter/setter combo).

    So, finally, your class would look something like this:
    Code:
    class Ship
    {
        private Area m_currentLocation;       // note: reference types default to null
        
        // this is a property; by convention, public members should use CamelCasing
        public Area CurrentLocation
        {
            get { return m_currentLocation; }
            set { m_currentLocation = value; }   // you can expand this to include, say, some checks
        }
    }
    That's pretty much it. Then you would access it the same way you described it in your OP (except that you would have to use the property name - like C++, C# is case-sensitive).
    The "value" you see up there is a contextual keyword (acts as a keyword inside properties, but otherwise it's not reserved) - it simply represents the object passed to the setter.
    So:
    Code:
    Ship theShip = new Ship();
    Area theArea = new Area();
    
    theShip.CurrentLocation = theArea;    // SETTER
    
    // later on, in doSomething()...
    theShip.CurrentLocation.someObject = newObject;      // GETTER. Note: you should use properties in Area as well.
    A few notes: the getter, as defined here, will simply return a reference to the internal object (both the internal and the external variable will point to the same object): this means that you can mutate the internal object by accessing and modifying it's members (directly, or via properties and methods). A setter will replace the internal object (unless you pass the same object to it for some reason). You can have both a get and a set block, or just one of them.
    Last edited by TheGreatCthulhu; April 6th, 2012 at 02:55 AM.

  3. #3
    Join Date
    Apr 2012
    Posts
    13

    Re: Pointer Workaround

    Thank you for your detailed response. Although I was aware that class variables were automatically passed to functions by reference, I did not know they were stored within classes by reference as well.

    Now a quick follow up question

    If I have two class instances, is there a way to assign only value of one instance to another, without a custom method/constructor? E.g. if I have


    Code:
                Ship testShip1 = new Ship(); //Line 1
                Ship testShip2 = new Ship(); //Line 2
                testShip2 = testShip1; //Line 3
    any modification of testShip2 will affect the Ship object instantiated in Line 1, whereas I want testShip2 to reference a separate Ship object which initially shares the same value as that created in line 1.

  4. #4
    Join Date
    Jan 2007
    Posts
    491

    Re: Pointer Workaround

    There are two options to do that:
    1. Define the Ship as a struct (yes, there are structs in C#). By doing that, the line testShip2 = testShip1; will actually copy the content of testShip1 into testShip2. However, unlike C++, structs should be used rarely, in very specific cases.
    2. Instead of the assignment in line 3, perform a deep copy of testShip1 and assign the result to testShip2 (google "C# deep copy" for more information about that).

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured