0

So, I am kind of used to structuring things like JavaScript and in light of that I do struggle in some areas in C#. Right now I'm trying to use structures in a way I can call a value using a variable that would match the value I'm going for.

For example my structure would be this:

public struct test
{
    public int[] valuesOne;
    public int[] valuesTwo;

    public test(int[] data) 
    {
        valuesOne = new int[2] { data[0], data[1] };
        valuesTwo = new int[2] { data[2], data[3] };
    }
}

Okay so say I have all of this and I want to get test.valuesOne[0] but from a variable like so:

string getValue = "valuesOne";
Console.Log(test[getValue][0]);

I know this provides a indexing error, but I'm in a situation where I kind of want this functionality. Sure I can pass my structure through a simple method, but if I can do it in a similar way to this without a huge problem I'd like to.

William
  • 1,175
  • 2
  • 17
  • 32

3 Answers3

0

c# and JavaScript are two different pairs of shoes. I try to do something similar as your code, however not sure if that's what you're looking for.

class Program
{
    static void Main(string[] args)
    {
        var t = new Test(new int[] { 1, 2, 3, 4 });
        var value = t["valueOne"][0];
        Console.WriteLine(value);

    }
}

public class Test
{
    private Dictionary<string, int[]> _data = new Dictionary<string, int[]>();

    public Test(int[] data)
    {
        _data.Add("valueOne", new int[] { data[0], data[1]});
        _data.Add("valueTwo", new int[] { data[2], data[3]});
    }

    public int[] this [string value]
    {
        get { return _data[value]; }
    }

}
gsharp
  • 27,557
  • 22
  • 88
  • 134
  • Thank you! If I didn't have to do some converting to a dictionary to a struct I would do this, and I still may depending. Thank you again! – William Nov 03 '19 at 07:16
  • @William what you mean? I don't really understand your comment. – gsharp Nov 03 '19 at 07:21
  • I'm using Unity and they can't convert Dictionarys into json format, so I'd have to convert them into a struct first, then convert them back on load. Which isn't a huge problem if the need to do so arises, but for now I think I'll be using a method with a switch statement. Mostly because my structures are small so its not a pain to do. – William Nov 03 '19 at 07:35
  • @William Can't you use another json library ? like JSON.NET ? – gsharp Nov 03 '19 at 08:04
  • Json.NET doesn't deserialize objects into lists very well (which is how I have my saving system as). I'm sure I could just add some extra steps for it to do it, though. I already have the system in place and changing it will take a bit more time I'd like to spend on it. – William Nov 04 '19 at 04:00
  • Json.NET (https://www.newtonsoft.com/json) does deserialize actually pretty good. Are you sure it's a Json.NET problem ? – gsharp Nov 04 '19 at 06:08
0

you can use dynamic + reflection + this[string key] to do it. but it needs some extra code.

note : it's a bad idea,this will lose the advantage of strong type checking.

demo :

void Main()
{
    var test = new test(new[] {1,2,3,4,5});
    Console.WriteLine(   test["valuesOne"][0]   ); //1
    Console.WriteLine(   test["valuesTwo"][1]   ); //4
}

public struct test 
{
    public int[] valuesOne;
    public int[] valuesTwo;

    public test(int[] data)
    {
        valuesOne = new int[2] { data[0], data[1] };
        valuesTwo = new int[2] { data[2], data[3] };
    }

    public dynamic this[string key]
    {
        get
        {
            return this.GetFieldValue(key);
        }
    }
}

public static class Extension
{
    public static object GetFieldValue(this object t, string fieldName)
    {
        var type = t.GetType();
        var fields = type.GetFields();
        var field = fields.Single(pi => pi.Name == fieldName);
        return field.GetValue(t);
    }
}

online demo link : can-you-get-a-value-in-a-structure-through-an-outside-variable-in-c | .NET Fiddle

Wei Lin
  • 3,591
  • 2
  • 20
  • 52
  • You could, but should you? This is a bad idea to begin with, wouldn't the OP benefit more from an answer that explains why it's a bad idea? – Zohar Peled Nov 03 '19 at 07:01
  • 1
    Hmm, Thank you! This would work nicely, especially because I do not need to do much with it, but since my project is ever growing "future proofing" would be a good way to handle this. So I either need to pass it through a method and get what I need (since it will be a simple thing to do). Or use a dictionary, however I would have to eventually convert it back to a structure (for saving). Thanks for letting me know it is a bad idea though! – William Nov 03 '19 at 07:14
  • @William this is really not a good solution, i wouldn't go for it. – gsharp Nov 03 '19 at 07:22
0

Usually I too would recommend using a Dictionary as in @gsharp's answer. But since that isn't an option for you, perhaps you could go with a Dictionary of delegates instead:

var accessor = new Dictionary<string, Func<test, int[]>>
{
    { nameof(test.valuesOne), x => x.valuesOne },
    { nameof(test.valuesTwo), x => x.valuesTwo }
};

Now you can access your data like so:

string getValue = "valuesOne";
Console.Log(accessor[getValue](test_instance)[0]);

You can extend this concept by wrapping this Dictionary into an Extension Method:

public static class Extensions
{
    private static new Dictionary<string, Func<test, int[]>> accessor =
        new Dictionary<string, Func<test, int[]>>
        {
            { nameof(test.valuesOne), x => x.valuesOne },
            { nameof(test.valuesTwo), x => x.valuesTwo }
        };

    public static int[] Property(this test t, string name)
    {
        return accessor[name](t);
    }
}

Then you can write:

Console.Log(test_instance.Property(getValue)[0]);