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

    Pointers - Unsafe

    Hi

    I'm rewriting some of my libraries in C#.

    I've read the manuals and tutorials but I cannot make it work.
    I specifically have the declaration of a node of a link list

    ie:

    Code:
    class  Node
        {
            private int id;
            (etc...)
                        
          Node*  next;  
    
        }
    I tried all combinations but I cannot make it work.
    Could you plz tell me how it is done in this particular example?

    Thanks

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

    Re: Pointers - Unsafe

    You don't need to use pointers - in C# there are two kinds of types: (1) value types (structs), which are passed around by value, and (2) reference types (classes), instances of which are really references to objects (garbage collected pointers of sort), and are thus effectively passed by reference. Basically, class instances behave akin to C++ pointers, except you don't have to delete them manually, and you're not allowed to do pointer arithmetic.

    So, you only need to declare it this way:
    Node next;
    // or
    Node next = null;


    And then when you add a node, you simply write:
    next = node;

    It essentially makes next point to a different object. You continue to use the member access operator (".") as usual.

    BTW, if it's relevant, the .NET library comes with a LinkedList<T> generic class (a doubly linked list).
    Last edited by TheGreatCthulhu; October 11th, 2012 at 06:41 AM.

  3. #3
    Join Date
    Mar 2001
    Posts
    2,529

    Re: Pointers - Unsafe

    CSharp uses the unsafe keyword as you know to allow you to use pointers. Unsafe code is very C-Like. I believe the closest you can get to a pointer to a user defined class is a pointer to a struct. This is done to allow inter-op with Win32 and other external C/C++ libraries and memory mapped devices. Other than that, you can make pointers to the built in types, that are also classes.

    http://msdn.microsoft.com/en-us/libr...=vs.71%29.aspx
    ahoodin
    To keep the plot moving, that's why.

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

    Re: Pointers - Unsafe

    If you have an interop scenario, you might need to use pointers and "unsafe" blocks, but, IMO, if you're rewriting code to C#, then, with reference types available, there's really no need for pointers.

  5. #5
    Join Date
    Oct 2012
    Posts
    18

    Re: Pointers - Unsafe

    Thanks to all of you guys.

    I did it without any unsafe, no real need, since there are "ref"s.

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

    Re: Pointers - Unsafe

    Sorry, just a question: when you say "ref"-s, did you use ref method parameters or did you mean reference types? If you used ref parameters, there's no need for that either.
    If that's the case, I'll explain about the ref later.

  7. #7
    Join Date
    Oct 2012
    Posts
    18

    Re: Pointers - Unsafe

    I use it to pass by reference. Can I overpass this too??

    for ex:
    void Change(ref string xy) { xy="hi";}

    string x = "hello"
    Change(ref x);
    //now x= "hi"';

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

    Re: Pointers - Unsafe

    OK, suppose you have this:

    Code:
            public static void Test(int val)
            {
                val = -val;
            }
    
            public static void Test(string val)
            {
                val = val.ToLower();    // ToLower() returns a new string, all in lowercase
            }
    
            public static void Test(Element val)
            {
                // mutate
                val.Value = "The Old New Thing";
    
                // replace
                val = new Element();
                val.Value = "New!";
            }
    What will the value of the original object be when the methods return? To answer that question, you must understand the distinction which C# makes between value types (structs) and reference types (classes). All the fundamental types (byte, int, long, float, double, bool...), except for string, are value types. They are passed around by value by default. String type is a reference type, but is specific in that it's, by design, immutable. That is, when you assign a new string to a variable, it's not the contents of the string objects that changes, but the whole object itself gets replaced. (This enables the language to share same string literals among string variables.) Now, for the code above, all of the variables are local copies, so replacing them will not have any effect on the original. So, the integer will not change, the original string will not be replaced, and the Element object (a reference type) will not be replaced, but it will be mutated (changed internally), and it's Value property will be "The Old New Thing".
    It's like when you pass a pointer to an object in C++: a local copy of the pointer is made, but it still points to the same object, so you can modify that object.

    Code:
    Originals:
    n: 5
    s: STRING!
    e: OLD
    
    No ref keyword:
    n: 5
    s: STRING!
    e: The Old New Thing

    Now, in C#, the ref keyword is a part of the signature, so you can overload all those methods, like this:
    Code:
            public static void Test(ref int val)
            {
                val = -val;
            }
    
            public static void Test(ref string val)
            {
                val = val.ToLower();
            }
    
            public static void Test(ref Element val)
            {
                // mutate
                val.Value = "The Old New Thing";
    
                // replace
                val = new Element();
                val.Value = "New!";
            }
    What happens now?
    For value types, it's straightforward - the ref keyword forces them to be passed by reference. For reference types, the reference itself is passed by reference - analogous to a C++ pointer being passed by reference. This means that you can now make it point to an entirely different object. So, after each of the methods returns, the original integer will be changed, the original string variable will point to a new string, and the original element variable will point to a new object, with the Value property set to "New!".
    Code:
    Originals
    n: 5
    s: STRING
    e: OLD
    
    Using ref
    n: -5
    s: string
    e: New!

    You can try calling these methods in a console application, in the Main() method, and see for yourself. Something like this:
    Code:
                int n = 5;
                string s = "STRING!";
                
                Element e = new Element();   // This is just some class (the one I used in your other thread, the linked list example)
                e.Value = "OLD";             // all it does is it stores a string value
    
                Console.WriteLine("Originals:");
                PrintValues(n, s, e);
    
                Test(n);
                Test(s);
                Test(e);
    
                Console.WriteLine("No ref keyword:");
                PrintValues(n, s, e);
    
                Test(ref n);
                Test(ref s);
                Test(ref e);
    
                Console.WriteLine("Using ref keyword:");
                PrintValues(n, s, e);
    PrintValues() is just a helper method:
    Code:
            private static void PrintValues(int n, string s, Element e)
            {
                Console.WriteLine("n: {0}", n);
                Console.WriteLine("s: {0}", s);
                Console.WriteLine("e: {0}", e.Value);
                Console.WriteLine();
            }
    P.S. In the IDE, you can discover if a type is a value type or a reference type by hovering a mouse over a type name and looking if it says struct or class. You can also rely on the MSDN documentation.
    Last edited by TheGreatCthulhu; October 12th, 2012 at 02:20 PM.

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

    Re: Pointers - Unsafe

    I just noticed that I didn't answer your question directly, so:
    Quote Originally Posted by dazibao View Post
    I use it to pass by reference. Can I overpass this too??

    for ex:
    void Change(ref string xy) { xy="hi";}

    string x = "hello"
    Change(ref x);
    //now x= "hi"';
    If you want to do it that way, then you must use the ref keyword, because, as I said, string is an immutable type. (There's also a mutable variant, called StringBuilder.) So, xy="hi" does not modify the original string object, it actually assigns a completely different object to the variable (read the post above for more detail). But if you had a regular, mutable object, such is, say, a Button (Win Forms), then this would work:
    Code:
    void Change(Button btn) { btn.Text = "Hi"; }
    
    Button b = new Button();
    b.Text = "Hello";
    Change(b);        // a reference type behaves a lot like a pointer, but it's garbage collected
    
    //now b.Text == "Hi"';
    This next variation wouldn't work without the ref keyword, though:
    Code:
    void Change(Button btn)    
    { 
        btn = new Button();   // Trying to replace the original object, which is what actually happens with strings
        btn.Text = "Hi";        // At this point, btn has nothing to do with the btn that was originally passed here
    }
    
    Button b = new Button();
    b.Text = "Hello";
    Change(b);
    
    //now, it's still: b.Text == "Hello"';
    If you have a linked list of elements which contain strings, then you can write an Add() or an Insert(), or a Replace() method without using the ref keyword:
    Code:
    public void Add(string item)
    {  /* ...assign item to an internal element... */  }
    The string, being a class, is passed as a reference to the original string object (analogous to a C++ pointer). In the case of the replace method, you can simply set the internal member variable using "someVar = item", and it will point to the original object.

    Basically, if it's a class, it behaves a lot like a pointer, if it's a struct, is just passed by value.
    Last edited by TheGreatCthulhu; October 12th, 2012 at 03:02 PM.

  10. #10
    Join Date
    Oct 2012
    Posts
    18

    Re: Pointers - Unsafe

    very enlightening posts GreatKthulu!!

  11. #11
    Join Date
    Oct 2012
    Posts
    18

    Re: Pointers - Unsafe

    Hi Again.

    I'm trying to pass a pointer to a string from one form to another.

    From Form1:
    private void bSave_Click(object sender, EventArgs e)
    {
    SaveQueryAs save = new SaveQueryAs(ref str);
    save.ShowDialog();
    }

    ---
    To form SaveQueryAs:

    public partial class SaveQueryAs : Form
    {
    string sRef = null;

    public SaveQueryAs(ref string str)
    {
    InitializeComponent();
    bOK.DialogResult = DialogResult.OK;
    sRef = str; //or str = sRef. Tried both
    }

    and later on when the form closes:

    private void bOK_Click(object sender, EventArgs e)
    {
    sRef = "Whatever";
    }
    It doesnt change the string back to the caller. I guess the new value can only be assigned in that method that takes the ref parameter, but this can't be done as you see.

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

    Re: Pointers - Unsafe

    There are 2 major problems with that.
    First, this doesn't work because although you assign str to the sRef variable, you are simply making it point to the same object. sRef is still a different variable. What's passed by reference to the function is str, so only assigning something to str will affect the original variable.

    Now, when you tried assigning str = sRef in the constructor, you did change to what the original variable points to, and if it was an object of a mutable type, the code in bOK_Click would affect it. Note that sRef and str are still different variables pointing to the same object, but this can change.
    And, as string is immutable, it does change in the click event handler, which is pretty much is equivalent to:

    Code:
    private void bOK_Click(object sender, EventArgs e)
    {
        sRef = new String("Whatever");    // sRef and str no longer point to the same object!
    }
    The second problem is that, even if the code worked, it breaks encapsulation - it tries to modify internal data of a different class, and that is not a good thing.

    The proper way to do it is to define a suitable public interface (by providing a set of public methods and/or properties) on the SaveQueryAs class, which can be used to retrieve the string object (or any other data).
    For example, take OpenFileDialog: once the user selects a file and closes the dialog, the form that has shown the dialog window can retrieve the path via the FileName property of the OpenFileDialog class.

    See this very simple article, or this code snippet.
    Code:
        if(openFileDialog1.ShowDialog() == DialogResult.OK)
       {
          System.IO.StreamReader sr = new 
             System.IO.StreamReader(openFileDialog1.FileName);
          MessageBox.Show(sr.ReadToEnd());
          sr.Close();
       }
    So, similarly, define a public property on the SaveQueryAs class; you can name it UserInput, or some other name you think is adequate, and then simply set the value of that property inside the bOK_Click handler.

    Then, when the SaveQueryAs dialog is closed, and the control flow returns to the bSave_Click method in Form1, you can simply do:
    str = save.UserInput;
    Last edited by TheGreatCthulhu; November 14th, 2012 at 09:03 AM.

  13. #13
    Join Date
    Oct 2012
    Posts
    18

    Re: Pointers - Unsafe

    d4mn!
    Not sure if I'm completely anti-OOP or just the common C++ past.

    I went with the second way. Why messing with all these? no need anymore..
    Last edited by dazibao; November 16th, 2012 at 08:31 PM.

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