C# List elements lifetime Unity3d - c#

I just used List of string to store words from json file. I parsed the json and stored the values in the List. My script looks like this.
public List <string> a = new List<string>();
void Start()
{
//JSON Parsing
var jd = JSONNode.Parse(jsonString);
print (jd.Count);
for(int no=0; no<jd["A"].Count;no++)
{
a.Add(jd["A"][no].Value);
}
print ("A => "+a.Count);
}
If I have 10 values from json, it is added to the List a. I get the print "A => 10". When I stop and run my project again my start method again does parsing and adds value to List a. But my List count is now 20. And if I run again, it will be 30 and so on. I tried it on device also. On device after uninstalling and again installing, I get it added to it and still get the count as 20. Is it always necessary to clear() the List in the Start() to make the count 0? If I am not doing Clear() before adding strings to List, it always keeps previous values even after stopping the app on editor and on device also.

Make the List private or use the "NonSerialized" attribute on the List variable if you are running your project in "ExecuteInEditMode".

Based on your comment about ExecuteInEditMode:
that will cause the list to be persisted
you might want that when, for example, you are live editing a level or environment
and you would want the final values/settings to persist across runs and builds.
Public fields would get serialized for persistence. NonSerialized attribute might
be useful to prevent that field from being persisted.
An alternate way would be to identify what values/state etc you want to persist and which
ones you want reset when actually playing and then do that accordingly.

Related

Unity add a listener form dictionary to a TextMeshProUGUI Text?

I am making a project with Unity that using RestSharp API's.
I can specify and retrieve language keys and values ​​from the server without any problems, and I can keep these values ​​up to date in a dictionary and listen. As soon as the values ​​arrive, that is, when the dictionary is updated, when I want to send the data to the texts, only the active ones in the hierarchy are updated.
public void SetTexts()
{
var languageTexts = FindObjectsOfType<LanguageKeys>();
foreach (LanguageKeys languageText in languageTexts)
{
languageText.SetTexts();
}
}
When I send the values ​​with these codes, they are written instead of the values ​​without any problems.
It also happens if I want to rerun the SetText() function with the OnEnable function, but when the values ​​are coming from the server, I get an error because the key values ​​in the Dictionary are null.
Is there a function like UnityEvent, Action<> where TextMeshProUGUI text can listen to the values ​​from the dictionary and update itself when the values ​​change? How can I improve the code so that it is a more optimized system?
FindObjectsOfType by default only returns active and enabled instances!
In newer Unity versions (2020.3) there is the optional parameter bool includeInactive so in order to include also the inactive ones you want to use
var languageTexts = FindObjectsOfType<LanguageKeys>(true);

Populate OutputBuffer from a List in PostExecute using C# transformer

The saga of trying to chop flat files up into useable bits continues!
You may see from my other questions that I am trying to wrangle some flat file data into various bits using C# transformer in SSIS. The current challenge is trying to turn a selection of rows with one column into one row with many columns.
A friend has very kindly tipped me off to use List and then to somehow loop through that in the PostExecute().
The main problem is that I do not know how to loop through and create a row to add to the Output Buffer programatically - there might be a variable number of fields listed in the flat file, there is no consistency. For now, I have allowed for 100 outputs and called these pos1, pos2, etc.
What I would really like to do is count everything in my list, and loop through that many times, incrementing the numbers accordingly - i.e. fieldlist[0] goes to OutputBuffer.pos1, fieldlist[1] goes to OutputBuffer.pos2, and if there is nothing after this then nothing is put in pos3 to pos100.
The secondary problem is that I can't even test that my list and writing to an output table is working by specifically using OutputBuffer in PostExecute, never mind working out a loop.
The file has all sorts in it, but the list of fields is handily contained between START-OF-FIELDS and END-OF-FIELDS, so I have used the same logic as before to only process the rows in the middle of those.
bool passedSOF;
bool passedEOF;
List<string> fieldlist = new List<string>();
public override void PostExecute()
{
base.PostExecute();
OutputBuffer.AddRow();
OutputBuffer.field1=fieldlist[0];
OutputBuffer.field2=fieldlist[1];
}
public override void Input_ProcessInputRow(InputBuffer Row)
{
if (Row.RawData.Contains("END-OF-FIELDS"))
{
passedEOF = true;
OutputBuffer.SetEndOfRowset();
}
if (passedSOF && !passedEOF)
{
fieldlist.Add(Row.RawData);
}
if(Row.RawData.Contains("START-OF-FIELDS"))
{
passedSOF = true;
}
}
I have nothing underlined in red, but when I try to run this I get an error message about PostExecute() and "object reference not set to an instance of an object", which I thought meant something contained a null where it shouldn't, but in my test file I have more than two fields between START and END markers.
So first of all, what am I doing wrong in the example above, and secondly, how do I do this in a proper loop? There are only 100 possible outputs right now, but this could increase over time.
"Post execute" It's named that for a reason.
The execution of your data flow has ended and this method is for cleanup or anything that needs to happen after execution - like modification of SSIS variables. The buffers have gone away, there's no way to do interact with the contents of the buffers at this point.
As for the rest of your problem statement... it needs focus
So once again I have misunderstood a basic concept - PostExecute cannot be used to write out in the way I was trying. As people have pointed out, there is no way to do anything with the buffer contents here.
I cannot take credit for this answer, as again someone smarter than me came to the rescue, but I have got permission from them to post the code in case it is useful to anyone. I hope I have explained this OK, as I only just understand it myself and am very much learning as I go along.
First of all, make sure to have the following in your namespace:
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
These are going to be used to get properties for the Output Buffer and to allow me to output the first item in the list to pos_1, the second to pos_2, etc.
As usual I have two boolean variables to determine if I have passed the row which indicates the rows of data I want have started or ended, and I have my List.
bool passedSOF;
bool passedEOF;
List<string> fieldlist = new List<string>();
Here is where it is different - as I have something which indicates I am done processing my rows, which is the row containing END-OF-FIELDS, when I hit that point, I should be writing out my collected List to my output buffer. The aim is to take all of the multiple rows containing field names, and turn that into a single row with multiple columns, with the field names populated across those columns in the row order they appeared.
if (Row.RawData.Contains("END-OF-FIELDS"))
{
passedEOF = true;
//IF WE HAVE GOT TO THIS POINT, WE HAVE ALL THE DATA IN OUR LIST NOW
OutputBuffer.AddRow();
var fields = typeof(OutputBuffer).GetProperties();
//SET UP AND INITIALISE A VARIABLE TO HOLD THE ROW NUMBER COUNT
int rowNumber = 0;
foreach (var fieldName in fieldList)
{
//ADD ONE TO THE CURRENT VALUE OF rowNumber
rowNumber++;
//MATCH THE ROW NUMBER TO THE OUTPUT FIELD NAME
PropertyInfo field = fields.FirstOrDefault(x = > x.Name == string.Format("pos{0}", rowNumber));
if (field != null)
{
field.SetValue(OutputBuffer, fieldName);
}
}
OutputBuffer.SetEndOfRowset();
}
if (passedSOF && !passedEOF)
{
this.fieldList.Add(Row.RawData);
}
if (Row.RawData.Contains("START-OF-FIELDS"))
{
passedSOF = true;
}
So instead of having something like this:
START-OF-FIELDS
FRUIT
DAIRY
STARCHES
END-OF-FIELDS
I have the output:
pos_1 | pos_2 | pos_3
FRUIT | DAIRY | STARCHES
So I can build a position key table to show which field will appear in which order in the current monthly file, and now I am looking forward into getting myself into more trouble splitting the actual data rows out into another table :)

Elasticsearch PUT documents in strange order

How do set elasticsearch to be adding new documents with PUT method at the end (or the beginning).
Now it's adding new ones sometimes at the end, sometimes in the middle.
I know I can sort results by some field, but I want to see them in browser just ordered by time added without any additional parameters
ES is simply a document store, i.e. there's no inherent insertion order. I'd simply go with adding ?sort=yourdatefield:desc to your URL and you're all set.
If you don't add any specific sort field, it will sort by score which defaults to 1.0, so the order is undefined actually.

Updating Grid items in a List

I have a list of Grid items called gridCache.
I have a TabItem called ti.
This line of code:
gridCache.Last().Name = ti.Name;
...is updating the Name property of every single Grid item in the list. It should just be updating the last item's Name property.
Why is it doing this?
Maybe I'm rubberducking here, but I've followed it through a break point while debugging and they all just update simultaneously when this line is called.
EDIT: I'd like to basically make 'copies' of flyGrid as it's modified to store them for later use. The idea is to use this to cache data from some SQL calls. Here's what I'm trying:
//some stuff that defines flyGrid
Grid cacheGrid = new Grid();
cacheGrid = flyGrid;
cacheGrid.Name = ti.Name;
gridCache.Add(cacheGrid);
After this recurs 3 or 4 times, the Name property of every item in the list is always the last name supplied.
How can I make a copy of flyGrid that is its own instance each time this code recurs?
SOLUTION EDIT:
I ended up solving the root problem in a completely different way. The idea was to get cached ReportParameterInfoCollection items to keep from talking to the database constantly.
I ended up creating a simple class for an object with two properties: one random string of letters, and a list of ReportParameterInfoCollection items.
This allowed me to populate this list as tabs are opened, and assign these tabs unique IDs that match the parameter information stored in this list of objects.
I didn't really solve the question, so I decided not to post this as an answer.
That would happen if every Grid is the same instance.
Make sure you're actually creating multiple instances when populating the list.

Array returning same values for all indexes

I created an object called Participant.
Now I want to have an array of my Participant objects so that I could show them in a datagrid.
Here are the codes I tried (for better understanding of the problem, I removed the loops and datagrid codes):
Participant[] list = new Participant[count];
Participant one = new Participant(name, address);
Participant two = new Participant(name2, address2);
list[0] = one;
list[1] = two;
However, when I get values of one participant like through a messagebox in this manner,
MessageBox.Show(list[0].getName());
all it reflects are the data of participant two. Same is true if I have 3 objects, all it reflects is the data last sent into the array.
I know it is possible to have array of objects so there must be something I'm doing wrong. Or is there a better way to do this?
With the code as presented, the only way I can think of causing that is if the backig field (in Participant) was declared "static". If so, remove the "static".
Otherwise; does the actual code do a "new" for the two objects? Or does it overwrite an object after adding it to the array? (which means you have the same object twice in the array).
I would expect ReferenceEquals(list[0], list[1]) to be false in a sane world - can you test this and let us know?
Final thought; is there a "foreach" in the real code? It could be the infamous captured variable problem...
If you are using a loop to populate your array, be sure you use the loop index as the index of the array when you assign the paticipant.
Debugging is an underrated skill... Set a breakpoint on the line where you create the array and add list as a watch, and expand it so you see the contents. Step through your code and hover over the parameters as you're creating the Participants to see the values being passed. Step over the statemens that add them to the list and verify in your watch that the correct item and values are in the array each time and that the existing values haven't changed.

Categories

Resources