-2

I got a portion of code to hold game variables.

The Var struct is a simple one:

struct Var{
/// <summary>
/// Name of variable. Unchangable
/// </summary>
public string Name { get; private set; }
/// <summary>
/// Value of variable. Can be changed via <see cref="Change(string)"/>.
/// </summary>
public string Value { get; private set; }

public Var(string s, string value) {
    this.Name = s;
    this.Value = value;
}


public void Change(string v) {
    new Debug("b", $@"Changing value from ""{Value}"" to ""{v}""", Debug.Importance.ERROR);
    this.Value = v;
    new Debug("b", $@"Result: ""{Value}""", Debug.Importance.ERROR);
}
}

(new Debug(string, string, Debug.Importance) is a function that simply calls Conosle.WriteLine() without using System in each file)

class GameVars is a list of those.

I use an indexer for getting a Var using a variable.

public string this[string s] {
    get => vars.Find(e => e.Name == s).Value;
    set {
        new Debug("a", $@"Attempt to change value of ""{s}"" to ""{value}"".", Debug.Importance.ERROR);
        if( vars.Find(e => e.Name == s).Name != null )
            vars.Find(e => e.Name == s).Change(value);
        else
            vars.Add(new Var(s, value));
        new Debug("a", $@"Result: ""{this[s]}""", Debug.Importance.ERROR);
    }
}

And when in GameVars.LoadFromFile(string s) I use

this[ident] = value;

new Debug("", $"When do i Fire? {this[ident]}", Debug.Importance.ERROR);

if( this[ident] != value )
    throw new System.Exception("Could not change value!");

I get following output:

[ERROR]( a ) Attempt to change value of "version" to "beta 0.0.0.1".
[ERROR]( b ) Changing value from "beta 0.0.0..1" to "beta 0.0.0.1"
[ERROR]( b ) Result: "beta 0.0.0.1"
[ERROR]( a ) Result: "beta 0.0.0..1"
[ERROR](  ) When do i Fire? beta 0.0.0..1
Exception thrown: 'System.Exception' in ITW.exe
An unhandled exception of type 'System.Exception' occurred in ITW.exe
Could not change value!

Why isn't the value changing?

I tried changing everything to public and nothing helped. I checked everything with Console.WriteLine() and there is nothing to override this value. It just does not change to new one.

Minimal runnable code on Rextester

SkillGG
  • 647
  • 4
  • 18
  • 1
    FYI, the "bracket getter/setter" is called an ["indexer"](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/indexers/). – Heretic Monkey May 03 '19 at 20:57
  • Thanks. Did not know. TIL. – SkillGG May 03 '19 at 20:59
  • 3
    Also known colloquially as an "indexed property". –  May 03 '19 at 21:00
  • value isnt a reserved word for the language? perhaps it isnt the problem but i think you are actually trying to access Value instead of value (i mean in the gamevars ) – nalnpir May 03 '19 at 21:06
  • @nalnpir where do you mean that? – SkillGG May 03 '19 at 21:09
  • 1
    Can you reduce this to a standalone console app that can be copied/pasted and debugged as-is so we can observe the behavior? – David May 03 '19 at 21:17
  • I'll try to do so. – SkillGG May 03 '19 at 21:19
  • 1
    Maybe it doesn't want to change because it enjoys being at the old value. – EJoshuaS - Stand with Ukraine May 03 '19 at 21:28
  • I made minimal runnable code and put it on Rextester (online c#) and changed throwing exception a bit faster there, becuase that's the first moment, when its different. – SkillGG May 03 '19 at 21:40
  • 1
    In the code on Rextester, `Var` is a struct. But above, `Var` is a class. That matters, because `vars.Find(e => e.Name == s).Change(value);` won't work the same for value types and reference types. – wimh May 03 '19 at 21:54
  • Oh. Sorry. My bad. I wasn't paying attention when writing this question and in Rextester I copied code and deleted unnecessary parts. I oversaw it. I edited it now. Why does Find works differently for classes and structs? Is changing `Var` to a class the only option? – SkillGG May 03 '19 at 22:07
  • 1
    For a struct, it returns a copy, so the original value is not changed; https://dotnetfiddle.net/mqVK1p – wimh May 03 '19 at 22:26
  • 1
    Oh! Okay. I didn't know that! Thank you. – SkillGG May 03 '19 at 22:28
  • 1
    @SkillGG Everything works differently for classes and structs. Not just Find. Structs are value types, not reference types. That affects Find. It affects a lot of other things too. – 15ee8f99-57ff-4f92-890c-b56153 May 04 '19 at 01:44
  • Yeah. I didn't know that. I just thought that structs are non-nullable and that's it. I will have to learn a bit more about them :) – SkillGG May 04 '19 at 10:58

1 Answers1

1

@wimh figured it out:

.Find() used with structs returns copy and does not change the original. Fiddle

Thanks

Code that fixed it, yet Var still remained a struct:

vars[vars.FindIndex(e => e.Name == s)] = new Var(s, value);

instead of

vars.Find(e=>e.Name==s).Change(value);

And I got rid of Var.Change as it was not useful anymore.

SkillGG
  • 647
  • 4
  • 18