I have a large static list which is basically a lookup table, so I initialise the table in code.
private class MyClass
{
private class LookupItem
{
public int Param1 { get; set; }
public int Param2 { get; set; }
public float Param2 { get; set; }
public float Param4 { get; set; }
}
private static List<LookupItem> _lookupTable = new List<LookupItem>()
{
new LookupItem() { Param1 = 1, Param2 = 2, Param3 = 3 Param4 = 4 },
new LookupItem() { Param1 = 5, Param2 = 6, Param3 = 7 Param4 = 8 },
//etc
}
}
The real LookupItem
has many more properties, so I added a constructor to allow for a more compact initialisation format:
private class MyClass
{
private class LookupItem
{
public int Param1 { get; set; }
public int Param2 { get; set; }
public float Param2 { get; set; }
public float Param4 { get; set; }
public LookupItem(int param1, int param2, float param3, float param4)
{
Param1 = param1;
Param2 = param2;
Param3 = param3;
Param4 = param4;
}
}
private static List<LookupItem> _lookupTable = new List<LookupItem>()
{
new LookupItem(1, 2, 3, 4),
new LookupItem(5, 6, 7, 8),
//etc
}
}
What I'd really like to do is use the collection initialiser format for the object itself so I can get rid of the new LookupItem()
on every line. eg:
private static List<LookupItem> _lookupTable = new List<LookupItem>()
{
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
//etc
}
Is this possible? I like to think it is because the KeyValuePair
's of a Dictionary<>
can be initialised in this way.
MSDN States:
Collection initializers let you specify one or more element intializers when you initialize a collection class that implements IEnumerable. The element initializers can be a simple value, an expression or an object initializer. By using a collection initializer you do not have to specify multiple calls to the Add method of the class in your source code; the compiler adds the calls.
Does this mean I need to implement IEnumerable
on my LookupItem
class and return each parameter? My class isn't a collection class though.
I think you need to make a custom collection instead of List. Call it LookupItemTable, for example. Give that collection an Add(int, int, float, float) method and have it implement IEnumerable. For example:
class LookupItem
{
public int a;
public int b;
public float c;
public float d;
}
class LookupItemTable : List<LookupItem>
{
public void Add(int a, int b, float c, float d)
{
LookupItem item = new LookupItem();
item.a = a;
item.b = b;
item.c = c;
item.d = d;
Add(item);
}
}
private static LookupItemTable _lookupTable = new LookupItemTable {
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 }
};
I've now tried the above code and it seems to work for me.
Quick fix : Make your own List
type with an Add
overload that takes multiple arguments:
class LookupList : List<LookupItem> {
public void Add(int Param1, int Param2, ... sometype ParamX) {
this.Add(new LookupItem() { Param1 = Param1, Param2 = Param2, ... ParamX = ParamX });
}
}
Now works exactly as you want:
private static LookupList _lookupTable = new LookupList() {
{1,2,3,4},
{2,7,6,3}
};
More fundamental answer:
You're mixing up object initializers and collection initializers. Put simply:
Object initializers are a syntactic trick that, in the background call the property set methods for each named property with the value specified.
Collection initializers are a syntactic trick that, in the background:
Array
type: Fill the array with the itemsIEnumerable
: Call the Add
method for each sub-bracketed set. That is all there is to it. Consider for example the following hack:
public class Hack : IEnumerable {
public int LuckyNumber { get; set; }
public double Total { get; private set; }
public void Add(string message, int operand1, double operand2, double operand3) {
Console.WriteLine(message);
this.Total += operand1 * operand2 - operand3;
}
public IEnumerator GetEnumerator() { throw new NotImplementedException(); }
}
class Program {
static void Main(string[] args) {
Hack h1 = new Hack() {
{ "Hello", 1, 3, 2},
{ "World", 2, 7, 2.9}
};
Console.WriteLine(h1.Total);
Hack h2 = new Hack() { LuckyNumber = 42 };
Console.WriteLine(h2.LuckyNumber);
}
}
You should never do this in a real program, but I hope examining this example and the results, especially if you debug step through it, will help you understand the initializers clearly and choose a good solution for your current scenario.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With