В настоящее время у меня возникла проблема при использовании автоматически созданного свойства для члена класса. Вызов метода класса должен обновить свойство, но похоже, что это не работает.
Я обновляю старый код C#, и VS2017 дает мне несколько советов по рефакторингу, например, частные члены с вручную предоставленными свойствами для автоматически сгенерированных свойств.
VS упрощает это с помощью пары щелчков мышью, и все компилируется отлично. Проблема в том, что код работает не так, как раньше.
Рассмотрим следующий пример сокращенного кода:
using System;
public class Program
{
struct A
{
public A(int x) : this()
{
X = x;
}
public int X { get; private set; }
public void Update(int y)
{
X += y;
}
}
class B
{
private A _secondVar;
public B()
{
}
public A MyVar { get; set; }
public A SecondVar
{
get { return _secondVar; }
protected set { _secondVar = value; }
}
public void Foo(int z)
{
MyVar.Update(z);
_secondVar.Update(z);
}
}
public static void Main()
{
B b = new B();
Console.WriteLine("BEFORE: b.MyVar: " + b.MyVar.X + ", b.SecondVar: " + b.SecondVar.X );
b.Foo(23);
Console.WriteLine("AFTER: b.MyVar: " + b.MyVar.X + ", b.SecondVar: " + b.SecondVar.X );
}
}
Результат:
BEFORE: b.MyVar: 0, b.SecondVar: 0
AFTER: b.MyVar: 0, b.SecondVar: 23
Я ожидал, что вызов MyVar.Update(z) обновит свойство, а последующие вызовы MyVar.X должны предоставить обновленное значение.
Это ожидаемое поведение или ошибка в C#?
создание структуры относительно редко, по большому счету; Структуры изменчивый фактически являются хорошей идеей никогда (хотя я бы допустил это для ref struct); если вы используете последние версии C#, практически все структуры должны быть объявлены как readonly struct
@MarcGravell: Я бы также подчеркнул, что «практически никогда» - это не довольно никогда. Я поддерживаю то, что семейство ValueTuple является изменчивым, хотя мне потребовалось некоторое время, чтобы взяться за дело.
@JonSkeet согласился - я был вполне осознан в своем хеджировании :) Но это одна из тех вещей, где неудобный ответ: «вам нужно, чтобы действительно очень точно понимал, что, почему и последствия»





Вы используете изменяемые структуры, что настоятельно не рекомендуется именно по этой причине.
Ваш код здесь:
public void Foo(int z)
{
MyVar.Update(z);
_secondVar.Update(z);
}
эквивалентно этому:
public void Foo(int z)
{
A tmp = MyVar; // Creates a copy
tmp.Update(z);
_secondVar.Update(z);
}
Ваш код _secondVar.Update(z) изменяет значение _secondVar, потому что вы вызываете его непосредственно для переменной. Это не относится к вашему свойству - использование метода получения свойства фактически вызывает метод, который возвращает значение, которое является копией значения переменной.
Если бы вы использовали классы, вы бы увидели ожидаемое поведение, потому что тогда вы не пытались бы изменить значение базовой переменной, а изменили бы содержимое внутри объекта, на который она ссылается.
возможно, стоит отметить (но не стоит добавлять ответ): в последних версиях C# используется действительно легко, чтобы не допустить ошибки изменяемых структур: readonly struct A { public A(int x) => X = x; public int X { get; } }
Какой вывод вы сделали ожидать и почему?