1

After some research into C# and some test with LINQ with easy examples. I wanted to apply this knowledge into my problem.

My DataStructure as seen from the variable screen (Visual Studio)

- wm
   - Nations
      - [0]
          - Name "USA"
          - stockpile 
            - [0]
                - Name "Coal"
                - Quantity "quantity"
                - Value "value"
      - [1] //Same as above

My attempt to access "Coal" has been:

var result = wm.Nations.Find(r => r.Name == "USA")
Console.WriteLine(result + " Result");

But only returns [EconomyTest.NationBuilder] which is an object. How can i extract a string from that object or at least point to USA and access to the stockpile?

Edit1: Data Structure Declaration

    //Declarations of Lists
    public List<ResourceTemplate> stockpile = new List<ResourceTemplate>();
    public List<Money> money = new List<Money>();
    public List<PopulationTemplate> population = new 
    List<PopulationTemplate>();

   public NationBuilder(string name)//Constructor 
    {
        this.Name = name;

        stockpile = new List<ResourceTemplate>();
        money = new List<Money>();
        population = new List<PopulationTemplate>();
    }
    //World Market (Where the actual storage happens)

    public WorldMarket()//Constructor
    {
       //Declaration list 
       Nations = new List<NationBuilder>();
    }

    internal List<NationBuilder> Nations {get; set;}

    public void AddToWorldMarket(NationBuilder nation)
    {
        Nations.Add(nation);
    }

    //Finally how it is managed/used:

    WorldMarket wm = new WorldMarket();//Helps with adding those newly 
    created nations into a List

        foreach (string name in NationNames)
        {
            NationBuilder nation = new NationBuilder(name);//Creates new 
            Objects nations and used the name provided before
            nation.AddResource("Coal", 500, 10);
            nation.AddResource("Water", 100, 10);
            nation.AddMoney(100);
            nation.AddPopulation(1000);

            wm.AddToWorldMarket(nation);

Edit2: Function asked in the comments

    public void AddResource(string itemName, int quantity,  float 
                         value)//Adds Resources to the stockpile
     {
    stockpile.Add(new ResourceTemplate {Name = itemName, Quantity = 
                                      quantity, Value = value });
     }
Jonalcaide
  • 560
  • 8
  • 21
  • Sure, i will edit it right now. – Jonalcaide Dec 29 '17 at 21:09
  • Mind adding the code of the "AddResource" method? – Dzyann Dec 29 '17 at 21:24
  • Also, could you say in words what you are trying to do? For example, Are you trying to list all the Resources of the Nation "USA" or are you trying to find the nations where you have "Coal" as a resource? – Dzyann Dec 29 '17 at 21:25
  • I'm trying to do Both things using LINQ. So far by debugging what happens is that only load the first Nation it finds and not USA (which is the second). – Jonalcaide Dec 29 '17 at 21:32
  • Are you populating this data as your code suggest in memory and then trying to query it? Can you share the `AddResource ` method and the `Nation ` class structure with its properties and same for the `Resources`? Also before doing the query, with the debugger make sure your structure has everything you think it has. – Dzyann Dec 29 '17 at 21:36
  • I am constantly checking the structure and is as it is shown at the start of this question. I added the AddResource() function. Nation class is also in the question. – Jonalcaide Dec 29 '17 at 21:38
  • @Servy I don't think this question is a duplicate of the one you mention. It may be of this one though: https://stackoverflow.com/questions/29242928/linq-to-select-parent-objects-where-child-objects-have-a-matching-child-object – Dzyann Dec 29 '17 at 21:56
  • @Dzyann They're not asking how to traverse a tree. They said they're traversing a tree, and when they try to print out a given value, it prints the type name instead. They don't have a problem with the code to traverse the tree (or at least not one that they asked about). – Servy Dec 29 '17 at 21:57
  • WhiteGlove, I cant post an answer because the question is marked as duplicate, but if your structure is as I understand it, you need: `var countryNamedUsa = wm.Nations.SingleOrDefault(x => x.Name == "USA");` and `var countriesWithCoal = wm.Nations.Where(x => x.stockpile.Any(y => y.Name == "Coal"));` – Dzyann Dec 29 '17 at 21:58
  • @Servy well from what I talked with the OP and seeing the errors he got with the answers bellow, the issue is that he doesn't know how to traverse the tree to get what they need. Although you are right he also has the issue of the question you marked, so nvm. – Dzyann Dec 29 '17 at 22:00
  • @Dzyann If they have some other problem, beyond the one that they've asked about, then they can ask about it in a new question, if they have failed to solve the problem on their own, and are are unable to find suitable answers when doing research. – Servy Dec 29 '17 at 22:02
  • i can access values this way Like this "var result = wm.Nations[0].stockpile[0].Name;" That makes result turn into a string which holds the string "Coal" But its not what i want, that way i will need to know the order in which things are loaded. – Jonalcaide Dec 29 '17 at 22:05
  • @Dzyann with your solution what i get is [namespace.NationBuilder] and i can access variables such as name like [countryNamedUsa.Name] but the output is null instead of the name USA or at least true (exists). The problem might be with those [0] and [1] where is the thing stored. The function might look into the data storage, find only [index] and returning null as Exception because there is no [USA]. That is what i think. – Jonalcaide Dec 29 '17 at 22:09
  • Well, when you do a query there is a chance it may not return values. The SingleOrDefault does that, you need to check if countryNamedUsa is null before accessing it. In the second case where you have countriesWithCoal you need to check if there were elements returned at all (Count > 0) before accessing the item. Also maybe what you want is directly the list of Coal resources? You can do something like `var coalFromCountries = wm.Nations.Where(x => x.stockpile.Any(y => y.Name == "Coal")).SelectMany(x => x.stockpile).Where(y=> y.Name == "Coal").ToList();` – Dzyann Dec 29 '17 at 22:20
  • i just tried the solution from the duplicate and it does not work as it says Null. I did the ToString() override. – Jonalcaide Dec 29 '17 at 22:23
  • @Dzyann I just tested your solution of coalFromCountries and the debug (at the variables screen) shows your variable getting this structure [0] -> Name, Quantity, Value. It should be this 5 times because there are 5 nations with the same Name, Quantity and Value but it's only 1. – Jonalcaide Dec 29 '17 at 22:31
  • it's returning Null every time even if i look for the index. – Jonalcaide Dec 29 '17 at 22:35
  • i will upload all the project somewhere if you want to help me. I require 20 reputation to use the chat. – Jonalcaide Dec 29 '17 at 22:37
  • I have 21 but it doesn't let me. Idk. I will upload the whole thing somewhere to download – Jonalcaide Dec 29 '17 at 22:43
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/162194/discussion-between-whiteglove-and-dzyann). – Jonalcaide Dec 29 '17 at 22:45

2 Answers2

0

Just specify the Name

Console.WriteLine(result.Name + " Result");

To access to stockpile you can iterate it;

foreach (var stock in result.stockpile)
{
    //stock.Name
}
lucky
  • 12,734
  • 4
  • 24
  • 46
0

Your entire result variable is just being written out to the console as it is just having its ToString method called to render it, I think what you want is:

Console.WriteLine(result.Name + " Result");

Optionally, if you want the object to show more when rendered to the console, you can override ToString yourself.

public override string ToString()
{
   return this.Name + ", stockpile count: " + this.stockpile.Length;
}
Steve Danner
  • 21,818
  • 7
  • 41
  • 51
  • This solution 'Console.WriteLine(result.Name + " Result");' gives an 'System.NullReferenceException' – Jonalcaide Dec 29 '17 at 21:18
  • I think you've got a different issue going on. Either `result` or `result.Name` is winding up being null. You need to figure out which one is null, and further troubleshooting can be done there. – Steve Danner Dec 29 '17 at 21:40
  • I am debugging everything in order to find it so far i think it is because those [0] and [1] from the array. I can access if i point to them and search inside those. Otherwise, that function does not enter there. – Jonalcaide Dec 29 '17 at 21:41
  • Like this "var result = wm.Nations[0].stockpile[0].Name;" That makes result turn into a string which holds the string "Coal". – Jonalcaide Dec 29 '17 at 21:42