Невозможно изменить возвращаемое значение ошибки c # - PullRequest
122 голосов
/ 17 ноября 2009

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

public Point Origin { get; set; }

Origin.X = 10; // fails with CS1612

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

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

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

Ответы [ 6 ]

163 голосов
/ 17 ноября 2009

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

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

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

Origin = new Point(10, Origin.Y);
7 голосов
/ 17 ноября 2009

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

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

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

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

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

get { return myOrigin; }

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

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

myOrigin.X = 10;

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

4 голосов
/ 25 апреля 2013

К настоящему времени вы уже знаете, что является источником ошибки. В случае, если конструктор не существует с перегрузкой для получения вашего свойства (в данном случае 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;

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

0 голосов
/ 15 января 2019

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

При этом, если вам не нужно писать код за свойством 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
0 голосов
/ 17 ноября 2009

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

0 голосов
/ 17 ноября 2009

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

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

Надеюсь, что в этом есть смысл

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...