简体   繁体   English

在C#中为可为空的结构的成员分配值

[英]Assigning value to member of nullable struct in C#

In C#, I have a struct like this: 在C#中,我有一个像这样的结构:

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

And another like this: 另一个像这样:

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

Now, I want to modify members of basing: 现在,我要修改基于以下内容的成员:

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

( uiState[0].stone is of type Tombstone ) uiState[0].stoneTombstone类型的)

First of these two calls works correctly, as I'm just changing a member of the array in basing , not the array itself. 首先这两个电话的正常工作,因为我只是改变了阵列的成员basing ,而不是数组本身。 However, the second complains: 但是,第二个抱怨:

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

It works if I do the same to mainSlab which is not nullable. 如果我对mainSlab进行同样的mainSlab这不能为空),则可以使用。 Is there a way to do this without copying the whole basing to a local variable for changes? 有没有一种方法可以在不将整个basing复制到局部变量进行更改的情况下进行此操作?

Is there a way to do this without copying the whole basing to a local variable for changes? 有没有一种方法可以在不将整个基础复制到局部变量进行更改的情况下进行此操作?

No, because Nullable<T> doesn't provide direct access to the underlying value field. 不可以,因为Nullable<T>不提供对基础值字段的直接访问。 You can't modify it "in place". 您不能“就地”修改它。

There are all kinds of little issues like this when you use mutable structs. 当您使用可变结构时,会有各种各样的小问题。 I'd strongly advise you to use classes or immutable structs whenever possible, to avoid these corner cases. 我强烈建议您尽可能使用类或不可变结构,以避免出现这些极端情况。

Frankly, the main error here is almost certainly: having a mutable struct. 坦白说,这里的主要错误几乎可以肯定:具有可变的结构。 Now, there are scenarios where mutable structs make sense, but those scenarios are narrow , and this almost certainly isn't one of them. 现在,在某些情况下可变结构是有意义的,但是这些情况很狭窄 ,几乎可以肯定不是其中之一。

Frankly, your code will be much easier to rationalize if you stop doing that ; 坦白说,如果您停止这样做,则代码将更容易合理化; with recent C#, you can even use readonly struct to help enforce this (and to get better behaviour with in ): 使用最新的C#,您甚至可以使用readonly struct来帮助实施此操作(并使用in获得更好的行为):

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

(personally I'd also consider properties instead of public fields, but that is a separate issue) (我个人也会考虑使用属性而不是公共字段,但这是一个单独的问题)

Then it becomes obvious that you can only assign the entire object: 然后很明显,您只能分配整个对象:

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

The only other alternative is basically to do the same thing anyway : 唯一的其他选择是基本上做同样的事情

Slab? foo = ...
// ...
var innerVal = foo.GetValueOrDefault(); // or .Value if you've already null-checked
// ...
innerVal.textureSrc = ...
foo = innerVal;

There may be many possible fixes for this "problem", depending on the rest of your design and requirements... For example: 此“问题”可能有许多可能的修复,具体取决于设计的其余部分和要求...例如:

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

To be honest I never user Nullables... Nullable value types, what's next, global rvalues? 老实说,我从未使用过Nullables ... Nullable值类型,接下来是什么,全局rvalues?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM