Reputation: 3988
I know this sounded stupid. But I gotta be doing something wrong here.
Say,
struct lala
{
private bool state1;
public lala(bool state1)
{
this.state1 = state1;
}
public void SetState1ToTrue()
{
this.state1 = true;
}
public bool GetState1()
{
return this.state1;
}
}
Then somewhere...
List<lala> lalas = new List<lala>();
lalas.Add(new lala(false));
lalas.Add(new lala(false));
lalas[0].SetState1ToTrue();
// Why is it False???
Console.WriteLine(lalas[0].GetState1());
Are there any workarounds to this except changing it to:
List<lala> lalas = new List<lala>();
lalas.Add(new lala(false));
lalas.Add(new lala(false));
lala newLala = lalas[0];
newLala.SetState1ToTrue();
lalas[0] = newLala;
// It's True, finally.
Console.WriteLine(lalas[0].GetState1());
Which looked awful, unelegant and wasted 2 lines of code. If there's any Linq-ish or Functional Programming-ish way in say 1 line of code that would be awesome.
Upvotes: 0
Views: 145
Reputation: 116724
Without changing it to a class (which is probably the right answer), the Linq-ish approach you asked for would be make the struct immutable, and so the "state changing" method would instead return a modified version. That way, you can't use it wrong.
struct lala
{
private readonly bool state1; // note: readonly
public lala(bool state1)
{
this.state1 = state1;
}
public lala SetState1ToTrue()
{
return new lala(true); // would copy any other fields, unchanged
}
public bool GetState1()
{
return this.state1;
}
}
Then you could "change" a whole list in one go:
List<lala> changed = original.Select(l => l.SetState1ToTrue()).ToList();
Though really you've created a brand new list - but that's structs for you.
Upvotes: 0
Reputation: 70353
Because struct
is always a value type, it is inherently immutable. This means that instead of doing:
lalas[0].SetState1ToTrue();
You should do:
lalas[0] = lalas[0].SetState1ToTrue();
There is an excellent article by Jon Skeet that explains in detail the differences between value types and reference types.
Upvotes: 0
Reputation: 12492
Structs are value types, so they are passed by value. That means that lalas[0] gives you a copy of the struct in lalas. You are changing a copy, so the original is unchanged.
Upvotes: 1
Reputation: 72930
The problem is in this line:
lalas[0].SetState1ToTrue();
The first part, lalas[0], retrieves the first lala from the list, and does so as a new copy of it in an implicit variable. So your SetState1ToTrue operates on a lala that is then immediately discarded, and the one in the list remains the same. It's the same as doing this:
lala newLala = lalas[0];
newLala.SetState1ToTrue();
If you make lala a class not a struct, so that it becomes a reference type, then the temporary variable (explicit or implicit) is a reference to the lala within the list.
Upvotes: 6
Reputation: 185693
Your issue that is that you're dealing with a struct, which is a value type, rather than a class, which is a reference type. The behavior you're expecting is that of a reference type. I would suggest just changing your declaration to a class (just given the simple example) and you shouldn't have an issue.
Upvotes: 0