Home>

I'm a beginner who has been doing C ++ for a while and has only been doing C # for a few days. Currently, I am migrating a library written in C ++ to C #.
I want to do something like the following code in C #, but I have no idea. I want to do something like a pointer in C/C ++.

class hoge {
    int n;
    public hoge (int N) {
        n = N;
    }
    public void draw () {
        Console.WriteLine ("{0}", n);
    }
}
public class Hello {
    public static void Main () {
        int x = 0;
        hoge Hoge = new hoge (x);
        for (int i = 0;i<10;i ++) {
            Hoge.draw ();// I want it to be displayed as 0,1,2,3, ...
            x ++;
        }
    }
}


In C ++

#include<iostream>
using namespace std;
class hoge {
    int * n;
public:
    hoge (int * N) {
        n = N;
    }
    void draw () {
        cout<<* n<<endl;
    }
};
int main (void) {
    int x = 0;
    hoge Hoge (&x);
    for (int i = 0;i<10;i ++) {
        Hoge.draw ();// 1,2,3, ...
        x ++;
    }
}


I want to

What I tried

I tried using pointers by wrapping the inside of hoge with unsafe, and tried out and ref, but it was not as expected.

Supplementary information (FW/tool version, etc.)

VisualStudio 2019 Community latest version
.NET Framework 4.7.2
C # 8.0

c#
  • Answer # 1

    If you convert the C ++ code to C # as it is

    unsafe class hoge
    {
        int * n;
        public hoge (int * N)
        {
            n = N;
        }
        public void draw ()
        {
            Console.WriteLine ("{0}", * n);
        }
    }
    class Program
    {
        unsafe static void Main (string [] args)
        {
            int x = 0;
            hoge Hoge = new hoge (&x);
            for (int i = 0;i<10;i ++)
            {
                Hoge.draw ();
                x ++;
            }
        }
    }

    I think it feels like. (Check the permission of the unsafe code and build.)

    However, in C # I think it's better to create a class that holds the value and pass an instance of it.

    class X
    {
        public int Value {get;set;} = 0;
    }
    class hoge
    {
        X n;
        public hoge (X N)
        {
            n = N;
        }
        public void draw ()
        {
            Console.WriteLine ("{0}", n.Value);
        }
    }
    class Program
    {
        static void Main (string [] args)
        {
            X x = new X ();
            hoge Hoge = new hoge (x);
            for (int i = 0;i<10;i ++)
            {
                Hoge.draw ();x.Value ++;
            }
        }
    }

    By the way, if you overload the operator, you can also perform operations on class X.

    "Operator overload"
    https://ufcpp.net/study/csharp/oo_operator.html

  • Answer # 2

    How about doing this?
    If the value is shared by multiple classes, it is a good idea to define the value as a class and share the instance.

    using System;
    class Hoge {
        public int X {get;set;} = 0;
        public void Draw () {
            Console.WriteLine ("{0}", x);
        }
    }
    public class Hello {
        public static void Main () {
            Hoge hoge = new Hoge ();
            for (int i = 0;i<10;i ++) {
                hoge.Draw ();
                hoge.X ++;
            }
        }
    }

  • Answer # 3

    It's a good idea to explore the difference between passing method arguments by value (default)/by reference (with ref qualifiers) and passing variable value/reference types to those arguments.

    By the way, int is a value type.

    The following article is for VB.NET, but the way of writing is different, but the idea is the same as C #, so please read it. You can understand it by reading ByVal as passing by value and ByRef as passing by reference.

    http://surferonwww.info/BlogEngine/post/2019/01/20/byval-byref-and-value-type-reference-type-in-vbnet.aspx

    In addition to ref, there are in and out, but if you google the difference, you will find many helpful articles, so please check it out.

    [Addition]

    I wrote the above answer thinking that it can be done by using reference passing/value passing properly, but due to a misunderstanding, it was not possible with the questioner's code example. I'm sorry.

    I will write a plan that I can do. I'm duplicating with the answers of other people.

    public class Hoge
    {
        public int Number {get;set;}
        public void Draw ()
        {
            Console.WriteLine (Number);
        }
    }
    class Program
    {
        static void Main (string [] args)
        {
            Hoge hoge = new Hoge ();
            hoge.Number = 0;
            for (int i = 0;i<10;i ++)
            {
                hoge.Draw ();
                hoge.Number ++;
            }
        }
    }

  • Answer # 4

    You can handle pointers in C # as well, but objects in managed memory are not always at the same address, so you need to explicitly fix the address (use GCHandle.Alloc or unsafe pointers). It seems that the efficiency of the garbage collector will decrease while fixing, so even if you use unsafe, it seems better to keep the scope within the method and not keep fixing it unnecessarily.

    Since assigning a value type only creates a copy, it must be stored in a reference type object to hold the reference.
    Value type and reference type

    I think that the solution is to prepare a property on the class side and access it, or create a class for storing values, as the types of other respondents have already been answered.

    Consider an alternative class for pointers. (It's just a story)

    class Pointer<T>{
        public T Value {get;set;}
        public Pointer () {}
        public Pointer (T value) =>Value = value;
        public static implicit operator T (Pointer<T>pVal) =>pVal.Value;
        public override string ToString () =>Value.ToString ();
    }


    Let's try to make the presented source similar using the above class.

    class Hoge
    {
        private Pointer<int>_pInt;
        public Hoge (Pointer<int>pInt)
        {
            _pInt = pInt;
        }
        public void Draw ()
        {
            Console.WriteLine ("{0}", _pInt);
        }
    }
    static void Main (string [] args)
    {
        var x = new Pointer<int>(0);
        Hoge hoge = new Hoge (x);
        for (int i = 0;i<10;i ++)
        {
            hoge.Draw ();// I want it to be displayed as 0,1,2,3, ...
            x.Value ++;
        }
        Console.ReadLine ();
    }
    (Execution result)
    0
    1
    2
    3
    Four
    Five
    6
    7
    8
    9


    With this, the desired operation has been achieved.
    However, as I wrote, I think that there are many parts that can be solved by design without using such a class, so
    If there is a part where the pointer is a member on the C ++ side after the transition to C #, it is better to review the way of holding the data.