Компилятор говорит, что я не могу взять адрес поля типа значения только для чтения

У меня есть структура:

struct S {
    public readonly int Value1;
    public readonly int Value2;
    public S(int value1, int value2) {
        this.Value1 = value1;
        this.Value2 = value2;
    }
}

и я пытаюсь взять адрес Value2:

var s = default(S);
unsafe {
    var r = new IntPtr(&s.Value2);
}

но я получаю ошибку компилятора:

Cannot take the address of the given expression

Я думал, что могу взять адреса полей? В чем дело?

2 ответа

Решение

Очевидно, он не работает с полями только для чтения. Меняем S на это:

struct S {
    public int Value1;
    public int Value2;
}

устраняет проблему

Имеет смысл, что значение только для чтения не может иметь указатель на него, потому что его значение может быть изменено путем разыменования указателя, что фактически нарушит его качество только для чтения.

Однако у меня есть решение для вас, но оно вам может не понравиться.

Во-первых, сделайте поля приватными и не только для чтения. Во-вторых, сделайте их доступными через свойства только для получения. В-третьих, добавьте свойства, которые возвращают указатели int на поля, не предназначенные только для чтения.

В качестве демонстрации:

struct S
        {
            private int value1;
            private int value2;
            public S(int value1, int value2)
            {
                this.value1 = value1;
                this.value2 = value2;
            }
            public int Value1 { get { return value1; } }
            public int Value2 { get { return value2; } }
            public unsafe IntPtr Value1Ptr
            {
                get
                {
                    fixed (int* ptr = &value1)
                    {
                        return new IntPtr(ptr);
                    }
                }
            }
            public unsafe IntPtr Value2Ptr
            {
                get
                {
                    fixed (int* ptr = &value2)
                    {
                        return new IntPtr(ptr);
                    }
                }
            }
        }

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

Другие вопросы по тегам