Basics
C# 3.0 introduced object and collection initializers.
Object initializers can be used with any type and let assign values to any accessible fields or properties at creation time.
Collection initializers let you specify one or more element initializers 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. (MSDN)
Implementation
Where is no need in additional coding to implement object initializers: you get them out of box.
Collection initializers are meaningful under certain conditions. Every decent C# book gives examples of Array
, List
and sometimes Dictionary
initialization. There is a simple receipt how to make your class support collection initialization if necessary.
Class has to implement:
IEnumerable
interface- Accessible
Add()
method
Look at the example (a bit artificial, but working):
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
namespace Demo
{
public class Vector : IEnumerable<double>
{
private readonly int _length;
private readonly double[] _coordinates;
private readonly bool[] _readState;
private int _index;
public Vector(int length)
{
if (length <= 0)
throw new ArgumentOutOfRangeException("length","Provide a positive value");
_length = length;
_coordinates = new double[_length];
_readState = new bool[_length];
_index = 0;
}
public double this[int index]
{
get { return _coordinates[index]; }
set
{
if (_readState[index])
throw new ReadOnlyException("Requested position is read-only");
_coordinates[index] = value;
}
}
public bool GetReadonly(int index)
{
return _readState[index];
}
public void SetReadonly(int index, bool value)
{
_readState[index] = value;
}
public IEnumerator<double> GetEnumerator()
{
return ((IEnumerable<double>) _coordinates).GetEnumerator();
}
public void Add(double value)
{
Add(value, false);
}
public void Add(double value, bool readState)
{
this[_index] = value;
SetReadonly(_index, readState);
_index++;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
And here is
the correct code which creates Vector
object:
var vector = new Demo.Vector(3)
{
1,
{3.14, true},
-1,
};
Intellisense knows about this syntax and shows a hint:
Pay
attention that both Add()
methods can be used in the same statement.
Collection initializers are easy-to-use and compact-looking. The only obstacle is that either an object initializer or a collection initializer can be used at a time (according to C# specification).