tags:

views:

1454

answers:

9

I want to initialize a static collection within my C# class - something like this:

public class Foo {
  private static readonly ICollection<string> g_collection = ???
}

I'm not sure of the right way to do this; in Java I might do something like:

private static final Collection<String> g_collection = Arrays.asList("A", "B");

is there a similar construct in C# 2.0?

I know in later versions of C#/.NET you can do collection initializers (http://msdn.microsoft.com/en-us/library/bb384062.aspx), but migration isn't an option for our system at the moment.

To clarify my original question - I'm looking for a way to succinctly declare a simple static collection, such as a simple constant collection of strings. The static-initializer-style way is also really good to know for collections of more complex objects.

Thanks!

+4  A: 

Perhaps you can call a static method:

public class Foo
{
    private static readonly ICollection<string> g_collection = initializeCollection();

    private static ICollection<string> initializeCollection()
    {
        ... TODO allocate and return something here ...
    }
}

Or, having a static constructor (as other people suggested) might be equivalent, or even more idiomatic.

ChrisW
A: 

The only way I can think of would be to have a static constructor. So first you new up a new collection at the class level, then in your static constructor, add all the values to it.

BFree
A: 

you could declare a custom collection class and add your own ctor to it...

  public class MyFooCollection: Collection<string>
   {
      public MyFooCollection(string[] values)
      {
          foreach (string s in values)  base.Add(s); 
      }
   }

then in your client code you could write

  private static final MyFooCollection g_collection = 
         new MyFooCollection(new string[] {"A", "B"});
Charles Bretana
+5  A: 

Static construction:

public class Foo
{
    private static readonly ICollection<string> _collection;

    static Foo()
    {
        _collection = new List<string>();
        _collection.Add("One");
        _collection.Add("Two");
    }
}

But note that in this case you can just initialize the collection inline (recommended for performance reasons):

private static readonly ICollection<string> _collection = new List<string>(new string[] { "One", "Two" });

It really depends on how complex your initialization code is.

HTH, Kent

Kent Boogaart
You can further enhance the readability of the code by tweaking the initialization a little further: ... = new List<string>() { "one", "two" };
BenAlabaster
+1 for the second suggestion.
Quibblesome
A: 

I like using IEnumerable<T>.ToList().
Also, if your collection should be readonly, you can use a System.Collections.ObjectModel.ReadOnlyCollection.

private readonly ICollection<string> collection = new string[] { "a", "b", "c" }.ToList();

private readonly ReadOnlyCollection<string> collection2 = new ReadOnlyCollection<string>(new string[] { "a", "b", "c" });

EDIT:
Then again, if you're using it as an ICollection, you can simply use the array constructor (since T[] is an IList<T> and an ICollection<T>). Keep in mind that in this case many alterring methods such as Add would fail:

private readonly ICollection<string> = new string[] { "a", "b", "c" };

EDIT #2: I just realized ToList is an extention function and can only be used in C# 3.0. You can still use the List constructor though:

private readonly IList<string> = new List<string>(new string[] { "a", "b", "c" });

Still, I prefer ReadOnlyCollection for read only lists.

configurator
A: 

Use a static constructor as follows:

public class Foo
{
    static readonly ICollection<string> g_collection;

    // Static constructor
    static Foo()
    {
        g_collection = new List<string>();
        g_collection.Add("Hello");
        g_collection.Add("World!");
    }
}
Juliet
A: 

besides of static constructor, this also will work

    public class Foo
    {
        private static readonly ICollection<string> _collection = 
              new List<string>(new string[] { "elem1", "elem2", "...", "elemn" });
    }
pablito
+15  A: 

If I fully understand your question, it seems some others have missed the point, you're looking to create a static collection in a similar manner to Java in that you can declare and populate in a single line of code without having to create a dedicated method to do this (as per some of the other suggestions). This can be done using an array literal (written over two lines to prevent scrolling):

private static readonly ICollection<string> Strings = 
  new string[] { "Hello", "World" };

This both declares and populates the new readonly collection with the item list in one go. Works in 2.0 and 3.5, I tested it just to be doubly sure.

In 3.5 though you can use type inference so you no longer need to use the string[] array which removes even more keystrokes:

private static readonly ICollection<string> Strings = 
  new[] { "Hello", "World" };

Notice the missing "string" type in the second line line. String is automatically inferred from the contents of the array initializer.

If you want to populate it as a list, just change up the new string[] for new List a la:

private static readonly ICollection<string> Strings = 
  new List<string>() { "Hello", "World" };

Of course, because your type is IEnumerable rather than a specific implementation, if you want to access methods specific to List< string> such as .ForEach(), you will need to convert it to List:

((List<string>)Strings).ForEach(Console.WriteLine);

But it's a small price to pay for migratability [is that a word?].

BenAlabaster
Yes, this was my intent - I'll edit the question to make it more clear. Thanks!
Aaron Whittier
A: 

You have two options:

  1. Use the return value of a static method to initialize the collection.

  2. Use a static constructor to create the collection, populate it and initialize it to the static variable.

From a performance perspective option 1 is better, since in the case of static constructors, the runtime has to check if the static constructor was called before every access to the class.

vboctor