Given your code, I have two concerns.
First, readonly references to mutable child objects (like collections) do not make the properties of the child immutable.
public class Foo
{
public readonly List<int> Bar = new List<int>{1,2,3};
}
...
var foo = new Foo();
//You may enumerate Bar and read its indices
foreach(int baz in foo.Bar) Console.WriteLine(baz.ToString());
var bob = foo.Bar[1];
//this is illegal because the reference is readonly
foo.Bar = new List<int>{4,5,6};
//but the properties of the immutable reference are still mutable, so this is fine:
foo.Bar.Clear();
foo.Bar.Add(4);
foo.Bar.Add(5);
foo.Bar.Add(6);
If you want a truly immutable child object, you have to make the reference immutable AND make sure the object itself is immutable. For that, you typically want to create or use a read-only version of your child and return that instead:
public class Foo
{
private readonly List<int> bar = new List<int>{1,2,3};
public ReadOnlyCollection<int> Bar { get { return bar.AsReadOnly(); } }
}
...
var foo = new Foo();
//You may still enumerate and index Bar
foreach(int baz in foo.Bar) Console.WriteLine(baz.ToString());
var bob = foo.Bar[1];
//this is illegal because there's no setter
foo.Bar = new List<int>{4,5,6};
//And these are also illegal because ReadOnlyCollection doesn't expose any such methods:
foo.Bar.Clear();
foo.Bar.Add(4);
foo.Bar.Add(5);
foo.Bar.Add(6);
Second, the locked, double-checked instantiation of the singleton is (much) better than nothing for making it thread-safe, but there are still some cases where this can fail to prevent double-instantiation. Microsoft instead recommends use of a static readonly field with instantiation defined:
public sealed class MySingl
{
public static readonly MySingl Instance = new MySingl();
private MySingl() { ... }
}
Microsoft guarantees an implementation like this to be thread-safe in the Microsoft CLR; statics are instantiated just-in-time and the CLR has internal mechanisms to block other threads that need this reference while it's being created.
Data is now (after parsing) stored in just a list, searching for a specific peace of data is not very well optimized. Are there other structures I could use, which I can search using file(string) - level(integer) - sub-level(integer) so I can quickly get a specific data object.
Assuming that you want to search by File, Level, Sub-Level only, you have a clear hierarchical structure in that description, it sounds like you can divide one ArrayList
into multiple steps. You could even make each hierarchy level a class itself to make it more clear, for example:
class SomeFileData {
List<LevelData> levels;
}
class LevelData {
List<SubLevelData> sublevels;
}
class SubLevelData {
// Probably similar to your current `FileData` implementation
}
And if you need to save multiple files at once, you can use a Map
with the file name as key.
class LotsOfFileData {
Map<String, SomeFileData> files;
}
Using this hierarchy, you can easily get file "mydata.dat", level 3, sublevel 4.
LotsOfFileData allData;
allData.getFile("mydata.dat").getLevel(3).getSublevel(4)
Each step in the get
process looks at the current class' list or map to retrieve the data.
By the way, declare variables according to their interface, not their implementation. Declare your ArrayList
s as List
to allow for easy change of implementation.
Best Answer
Regular expressions work on strings, not on a "string list" and not multiple string lists. Wherever you need to process more than one string, you will typically need some environmental code to do the processing. For your example, this code has to apply the regex to every element of the first list, then collect the results and use this results to process the second list.
Said that, the usual approach to apply a regexp to a list of strings is to concatenate them by a separator character like "newline". To concatenate two lists and distinguish them, you would need at least a special "magic" character or word for separating the first list from the second, which is not part of the list. Using such magic can cause some maintenance headaches if you are not very careful, nevertheless by combining this with backreferences, this can be used to solve your problem.
For example, numbered backreferences like
\1
to\9
refer to other capturing groups found before. Lets assume you used "###" as a separator for the two lists, a regexp along the lines ofmight be a first approximation for what you are looking for (beware of bugs, I did not test it). Put this into a global regexp search, then it should produce all pairs of matches which fit to your constraints.
As a final remark: the resulting code may be very compact, nevertheless harder to maintain (and probably slower) than a more explicit solution where you process the two lists individually.