Home > Net >  C# copying an immutable struct with modification?
C# copying an immutable struct with modification?

Time:05-26

Update: I'm using Unity 2020 so only have access to .Net 4

I have several immutable structs that contain info e.g.

public struct Human {
  public readonly string Name;
  public readonly string Age;
  // ... 50 other variables that describe a human
}

Now I want to clone a Human struct, but change 1 value only. I can of course do it like this:

var newSelf = new Human(
  oldSelf.Name,
  oldSelf.Age   1,
  // ... 50 more lines here
)

But as you can see it'll be really tedious to type oldSelf.XYZ 50 times for every single struct I made.

So I'm looking for something like this:

// copy all variable from oldSelf to a new struct, but change the name and increase Age by 1
var newSelf = oldSelf.CloneWithModification(("Name", "Valeria"), ("Age", oldSelf.Age   1));

I am not too keen on a struct precisely. What I need is actually just:

  • An immutable type that can be passed to another module (without worrying about the receiver modifying content affecting sender).
  • Easy cloning with small modifications.

CodePudding user response:

You can use records, introduced in C# 9, or if being a value type is also a requirement, use record structs, introduced in C# 10.

public record Human {
  public string Name { get; init; }
  public int Age { get; init; }
  // ... 50 other variables that describe a human
}

Then you can use the with expression to create a copy of a Human, with only some properties changed. Note that this uses the init accessor.

Human human = ...
var newHuman = human with { Age = human.Age   1 }; // this creates a copy

CodePudding user response:

I do not know if this is the answer to your question. But I suggest you run this method to solve the problem. Delete readonly first if not necessary.

public struct Human {
    public string Name;
    public int Age;
}

Create a default value of the variables as oldSelf and then get clones of it.

public void Start()
{
    var oldSelf = new Human
    {
        Name = "Human",
        Age = 56
    };

    var clone1 = oldSelf;
    clone1.Name = "Black "   clone1.Name;
    
    var clone2 = oldSelf;
    clone2.Age  ;

    Debug.Log(clone1.Name); // Black Human
    Debug.Log(clone2.Age); // 57
}

CodePudding user response:

Without using record you can follow the following pattern

public Human WithName(string value)
   => value == Name
      ? this
      : new Human(value, Age, ...);

public Human WithAge(int value)
   => value == Age
      ? this
      : new Human(Name, value, ...);

...
  • Related