Присвоение значения члену допускаемой с нуля структуры в C # - PullRequest
0 голосов
/ 29 июня 2018

В C # у меня есть такая структура:

public struct Slab
{   public float[] sizeM;
    public string textureSrc;
    //more members, not relevant here...
}

И еще один такой:

public struct Tombstone
{   public Slab mainSlab;
    public Slab? basing;
    //more...
}

Теперь я хочу изменить членов basing:

uiState[0].stone.basing.Value.sizeM[2] = Int32.Parse(breadthField.Value) / 100.0f;
uiState[0].stone.basing.Value.textureSrc = fileName;

(uiState[0].stone относится к типу Tombstone)

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

Cannot modify the return value of 'Slab?.Value' because it is not a variable

Это работает, если я делаю то же самое с mainSlab, который не обнуляется. Есть ли способ сделать это, не копируя весь basing в локальную переменную для изменений?

Ответы [ 3 ]

0 голосов
/ 29 июня 2018

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

Честно говоря, ваш код будет намного проще рационализировать, если вы перестанете это делать ; в недавнем C # вы даже можете использовать readonly struct, чтобы помочь реализовать это (и улучшить поведение с помощью in):

public readonly struct Slab
{   public readonly float[] sizeM;
    public readonly string textureSrc;
    //more members, not relevant here...
}

(лично я бы также рассматривал свойства вместо открытых полей, но это отдельная проблема)

Тогда становится очевидным, что вы можете назначить только весь объект:

Slab? foo = ...
... some logic
foo = new Slab(size, textureSource); // perhaps taking new values from the old

Единственная другая альтернатива - это в основном , чтобы делать то же самое в любом случае :

Slab? foo = ...
// ...
var innerVal = foo.GetValueOrDefault(); // or .Value if you've already null-checked
// ...
innerVal.textureSrc = ...
foo = innerVal;
0 голосов
/ 01 марта 2019

Может быть много возможных исправлений этой «проблемы», в зависимости от остальной части вашего дизайна и требований ... Например:

public struct Tombstone
{
  public Slab mainSlab;
  public Slab basing;
  public bool hasBasing => basing.sizeM != null;
  //more...
}

Если честно, я никогда не использую Nullables ... Типы значений Nullable, что дальше, глобальные значения?

0 голосов
/ 29 июня 2018

Есть ли способ сделать это, не копируя весь базис в локальную переменную для изменений?

Нет, поскольку Nullable<T> не обеспечивает прямой доступ к базовому полю значения. Вы не можете изменить его "на месте".

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

...