Ошибка: "Невозможно изменить возвращаемое значение" c #

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

public Point Origin { get; set; }

Origin.X = 10; // fails with CS1612

Сообщение об ошибке: Невозможно изменить возвращаемое значение выражения, потому что это не переменная

Была предпринята попытка изменить тип значения, который был результатом промежуточное выражение. Поскольку значение не сохраняется, значение будет неизменным

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

Ответ 1

Это потому, что Point - тип значения (struct).

Из-за этого при доступе к свойству Origin вы получаете доступ к копии значения, хранящегося в классе, а не о самом значении, как это было бы со ссылочным типом (class), поэтому, если вы установите свойство X на нем, тогда вы устанавливаете свойство на копии и затем отбрасываете его, оставляя исходное значение неизменным. Возможно, это не то, что вы намеревались, поэтому компилятор предупреждает вас об этом.

Если вы хотите изменить только значение X, вам нужно сделать что-то вроде этого:

Origin = new Point(10, Origin.Y);

Ответ 2

Использование переменной резервного копирования не поможет. Тип Point - это тип значения.

Вам необходимо присвоить целое значение Point свойству Origin: -

Origin = new Point(10, Origin.Y);

Проблема заключается в том, что при доступе к свойству Origin то, что возвращается get, является копией структуры Point в поле автогенерации исходного свойства. Следовательно, ваша модификация поля X эта копия не повлияет на базовое поле. Компилятор обнаруживает это и дает вам ошибку, так как эта операция абсолютно бесполезна.

Даже если вы использовали свою собственную поддерживающую переменную, ваш get будет выглядеть так: -

get { return myOrigin; }

Вы все равно возвращаете копию структуры Point, и вы получите ту же ошибку.

Хмм... более внимательно прочитав ваш вопрос, возможно, вы на самом деле хотите изменить переменную поддержки непосредственно из своего класса: -

myOrigin.X = 10;

Да, это было бы то, что вам нужно.

Ответ 3

Теперь вы уже знаете, что является источником ошибки. В случае, если конструктор не существует с перегрузкой, чтобы взять ваше свойство (в данном случае X), вы можете использовать инициализатор объекта (который будет делать всю магию за кулисами). Не нужно, чтобы ваши структуры не были неизменными, но просто добавили дополнительную информацию:

struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

class MyClass
{
    public Point Origin { get; set; }
}

MyClass c = new MyClass();
c.Origin.X = 23; //fails.

//but you could do:
c.Origin = new Point { X = 23, Y = c.Origin.Y }; //though you are invoking default constructor

//instead of
c.Origin = new Point(23, c.Origin.Y); //in case there is no constructor like this.

Это возможно, потому что за кулисами это происходит:

Point tmp = new Point();
tmp.X = 23;
tmp.Y = Origin.Y;
c.Origin = tmp;

Это выглядит очень странно, не рекомендуется. Просто перечислите альтернативный путь. Лучший способ сделать это: сделать структуру неизменной и создать соответствующий конструктор.

Ответ 4

Я предполагаю, что здесь уловка заключается в том, что вы пытаетесь назначить субъекты объекта в инструкции, а не назначать сам объект. В этом случае вам нужно назначить весь объект Point, так как тип свойства - Point.

Point newOrigin = new Point(10, 10);
Origin = newOrigin;

Надеюсь, я имел смысл там

Ответ 5

Проблема заключается в том, что вы указываете на значение, находящееся в стеке, и значение не будет возвращено обратно в свойство orignal, поэтому С# не позволит вам вернуть ссылку на тип значения. Я думаю, вы можете решить это, удалив свойство Origin и вместо этого используйте публичную подачу, да, я знаю, что это нехорошее решение. Другое решение состоит в том, чтобы не использовать Точку и вместо этого создать свой собственный тип Точки в качестве объекта.

Ответ 6

Помимо обсуждения плюсов и минусов структур по сравнению с классами, я склонен смотреть на цель и подходить к проблеме с этой точки зрения.

При этом, если вам не нужно писать код за свойством get и set методов (как в вашем примере), то не будет ли проще просто объявить Origin как поле класса, а не как свойство? Я должен думать, что это позволит вам достичь вашей цели.

struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

class MyClass
{
    public Point Origin;
}

MyClass c = new MyClass();
c.Origin.X = 23;   // No error.  Sets X just fine

Ответ 7

Просто удалите свойство "get set", как показано ниже, и тогда все будет работать как всегда.

В случае примитивных типов instread используйте get; set;...

using Microsoft.Xna.Framework;
using System;

namespace DL
{
    [Serializable()]
    public class CameraProperty
    {
        #region [READONLY PROPERTIES]
        public static readonly string CameraPropertyVersion = "v1.00";
        #endregion [READONLY PROPERTIES]


        /// <summary>
        /// CONSTRUCTOR
        /// </summary>
        public CameraProperty() {
            // INIT
            Scrolling               = 0f;
            CameraPos               = new Vector2(0f, 0f);
        }
        #region [PROPERTIES]   

        /// <summary>
        /// Scrolling
        /// </summary>
        public float Scrolling { get; set; }

        /// <summary>
        /// Position of the camera
        /// </summary>
        public Vector2 CameraPos;
        // instead of: public Vector2 CameraPos { get; set; }

        #endregion [PROPERTIES]

    }
}