Problem: I need to create a collection with string keys, that have two fields, which contain an array of string keys. This will be referenced in multiple functions inside the .cs file's namespace section, not just in a single function or class. The data inside it will not change, outside of its initialization.
In Lua, this is extremely trivial and easy to do. Like so:
local tableCulturesToRaceGender = {};
tableCulturesToRaceGender["Northern Empire"] = {
male={
"EmpireMale",
"BattaniaMale",
"KhuzaitMale"},
female = {
"EmpireFemale"
}
}
--[[
--Visual layout of the nested array
tableCulturesToRaceGender["Northern Empire"]
male
[1] = "EmpireMale"
[2] = "BattaniaMale"
[3] = "KhuzaitMale"
female
[1] = "EmpireFemale"
--]]
local function UseTheTable()
local strEntry = tableCulturesToRaceGender["Northern Empire"].male[2]
--StrEntry is now filled with: BattaniaMale
end
I'm having a hell of a time figuring this out. All sort of caveats, boilerplate, {get; set;} drudgery, getter and setter functions, stuff about mutability, how you can't readonly list<>, etc. And then there's the scope; putting a list in a namespace cannot be done, putting it in a class doesn't work due to mutability, etc.
It's an overcomplicated mess, with lots of jargon intended for people who already know what everything means. I've been at this for a couple hours, and I'm more confused than when I started.
So, how do I go about this?
CodePudding user response:
Use classes and generic containers for your data. You can initialize a class so that clients cannot change the data using private fields that can only be geted and not seted by a public property (that is C# jargon and if you want to use C#, you must learn it---sorry). You can use an interface so that the different 'empires' have the same kind of data but different values (and more optional stuff if needed). This is one approach that is very idiomatic in C#:
using System;
using System.Collections.Generic;
namespace Culture
{
public interface IRaces
{
public string Empire { get; }
public List<string> Male { get; }
public List<string> Female { get; }
}
public class NorthernEmpire : IRaces
{
private readonly string _empire = "Northern";
public string Empire => _empire;
private readonly List<string> _male = new() { "Empire", "Battania", "Khuzait" };
public List<string> Male => _male;
private readonly List<string> _female = new() { "Empire" };
public List<string> Female => _female;
private readonly string _fightingStyle = "whatever";
public string FightingStyle => _fightingStyle;
}
public class SouthernEmpire : IRaces
{
private readonly string _empire = "Southern";
public string Empire => _empire;
private readonly List<string> _male = new() { "Empire" };
public List<string> Male => _male;
private readonly List<string> _female = new() { "Empire", "Battania", "Khuzait" };
public List<string> Female => _female;
}
internal class Program
{
static void Main()
{
List<IRaces> raceList = new();
raceList.Add(new NorthernEmpire());
raceList.Add(new SouthernEmpire());
foreach (IRaces races in raceList)
{
Console.WriteLine($"Empire: {races.Empire}:");
foreach (string maleRace in races.Male)
Console.WriteLine($"\tMale race: {maleRace}");
foreach (string femaleRace in races.Female)
Console.WriteLine($"\tFemale race: {femaleRace}");
if (races is NorthernEmpire)
Console.WriteLine($"\tFighting Style: {((NorthernEmpire)races).FightingStyle}");
}
}
}
}
Output:
Empire: Northern:
Male race: Empire
Male race: Battania
Male race: Khuzait
Female race: Empire
Fighting Style: whatever
Empire: Southern:
Male race: Empire
Female race: Empire
Female race: Battania
Female race: Khuzait
CodePudding user response:
A pretty much word for word translation of your Lua code would be like:
var tableCulturesToRaceGender = new
{
northernEmpire = new
{
male = new[]
{
"EmpireMale",
"BattaniaMale",
"KhuzaitMale"
},
female = new[]
{
"EmpireFemale"
}
}
};
var result = tableCulturesToRaceGender.northernEmpire.male[0];
I'm having a hell of a time figuring this out. All sort of caveats, boilerplate, {get; set;} drudgery, getter and setter functions, stuff about mutability, how you can't readonly list<>, etc. And then there's the scope; putting a list in a namespace cannot be done, putting it in a class doesn't work due to mutability, etc.
Careful with that rant, it only shows you didn't bother to read any documentation. You haven't said a single true word in that entire paragraph, not to mention the next one.
CodePudding user response:
Have you considered using Enumerations in C# ? In your collection, add a get-only property with the enum below as output type. Enumerations are not mutable as they're constants in reality. And you can decorate each entry with custom attribute if you want too.
enum MaleEntries
{
EmpireMale = 1,
BattaniaMale = 2,
KhuzaitMale = 3
}
and
enum FemaleEntries
{
EmpireFemale = 1
}
