Небезопасные структуры в C# - PullRequest
1 голос
/ 15 апреля 2020

Я хотел попробовать небезопасную «особенность» c#, создавая простые структуры (Вектор, Частица).

СИТУАЦИЯ

У меня есть 2 структуры и хочу ввести векторы положения и скорости в мою структуру Particle . В качестве теста я хотел распечатать значение X позиции, но каким-то образом я получаю случайные значения.

У меня есть следующий код здесь

Вектор

public readonly struct Vector
{
    public int X { get; }
    public int Y { get; }

    public Vector(int x, int y)
    {
        X = x;
        Y = y;
    }
}

Частица

public unsafe struct Particle
{
    private Vector* mPosition;
    private Vector* mVelocity;

    public Particle(Vector position, Vector velocity = default)
    {
        mPosition = &position; // here is x 10
        mVelocity = &velocity;
    }

    public int GetPosX()
    {
        return mPosition->X; // but here not
    }
}

Программа

public class Program
{
    private static void Main(string[] args)
    {
        var pos = new Vector(10, 5);
        var obj = new Particle(pos);

        Console.WriteLine(obj.GetPosX()); // prints random value
    }
}

ПРОБЛЕМА

Он печатает случайное значение вместо 10.

Ответы [ 2 ]

1 голос
/ 15 апреля 2020
class Program {
    static void Main (string [ ] args) {
        unsafe {
            Vector pos = new Vector(10, 5);
            Particle obj = new Particle(&pos);
            // &pos is at position 0xabcdef00 here.
            // obj.mPosition has a different value here. It points to a different address? Or am I misunderstanding something
            Console.WriteLine(obj.GetPosX( ));
        }
    }
}

public struct Vector {
    public int X;
    public int Y;

    public Vector (int x, int y) {
        X = x;
        Y = y;
    }
}

public unsafe struct Particle {
    private Vector* mPosition;

    public Particle (Vector *position) {
        mPosition = position; // here is x 10
    }

    public int GetPosX ( ) {
        return mPosition->X; // still 10 here
    }
}

Это работает для меня. Пожалуйста ... не спрашивайте меня, почему это так. Вы заметите, что я не сильно изменился. Просто вызывая Particle с * pos вместо pos. По какой-то причине это решает проблему. Вы должны обернуть код небезопасным и, очевидно, изменить конструктор для Particle.

Я мог бы предположить, почему он работает, но я бы предпочел, чтобы это было не так. Может быть, указатель изменится, когда вы передадите pos в качестве параметра по какой-то причине?

0 голосов
/ 15 апреля 2020

Вы не могли бы получить ссылку с правильным значением.

Создать переменную типа int posX = 10;

И вы можете взять ссылку с переменной. Вы берете ссылку на время компиляции и читаете ссылку на среду выполнения.

Не используйте указатели без фиксированного значения. C# производительность стека очень хорошая. Вам это не нужно.

Обычно указатели используют со связыванием (C / Cpp dynamici c связывание библиотеки et c). Если у вас большие структуры (30 байт и более), вы можете использовать тег параметра ref.

...