I'd like to start off with that I'm new to C# so accessors and Object Initializers are a completely new concept to me. That said, I think I have an okay handle on them except the following example is really confusing me:
using System;
using System.Collections.ObjectModel;
class How {
public ObservableCollection<int> Coll {
get { return coll_; }
set {
Console.WriteLine("Setter for Coll Called!");
coll_.Clear();
foreach (int i in value)
coll_.Add(i);
}
}
public string Field {
get { return field_; }
set {
Console.WriteLine("Setter for field called");
field_ = value;
}
}
// To confirm the internal coll_ is actually set
public void Test() {
foreach(int i in coll_)
Console.Write(i + " ");
}
public How() {
coll_ = new ObservableCollection<int>();
field_ = "";
}
private ObservableCollection<int> coll_;
private string field_;
}
public class Test {
public static void Main() {
var how = new How {
Coll = { 1, 2, 3, 4, 5 },
Field = "Test Field",
};
Console.Write("Coll: ");
foreach (int i in how.Coll)
Console.Write(i + " ");
Console.WriteLine();
Console.WriteLine("Field: " + how.Field);
Console.Write("Internal coll_: ");
how.Test();
Console.WriteLine();
}
}
The output of the above code is (see live example here):
Setter for field called
Coll: 1 2 3 4 5
Field: Test Field
Internal coll_: 1 2 3 4 5
Field
operates exactly as I'd expect it to, but Coll
confuses me. The setter to Coll
is never called, which to me implies that Collection Initializers don't mix will with Properties (or at least non Auto-Properties). However, if that's the case, I would have expected a compile-time error.
Regardless of that part of the behavior, what confuses me even further is that the internal value of coll_
is somehow set to the initializer value.
I'm interested in knowing a) why Coll
's set is not called, and also how C# is able to set the value of coll_
. Is the use of that identifier in the get and set accessors for Coll
enough for C# to identify coll_
as the internal storage; or maybe since it's set because it's the only member of the corresponding type?
var how = new How
{
Coll = { 1, 2, 3, 4, 5 },
Field = "Test Field",
};
this is a object initialization syntax for How
class.
Coll = { 1, 2, 3, 4, 5 }
is a form of collection-itializer syntax meant for collection properties which don't have public setter (but works equally well with those which have setter). This form requieres for Coll
to be instantiated (be not null
): try to comment coll_ = new ObservableCollection<int>();
line in constructor and the program will crash with NullReferenceException.
Coll = { 1, 2, 3, 4, 5 }
is translated in repeated Coll.Add
calls:
Coll.Add(1);
Coll.Add(2);
Coll.Add(3);
Coll.Add(4);
Coll.Add(5);
to confirm it add event handler in How
constructor:
public How()
{
coll_ = new ObservableCollection<int>();
coll_.CollectionChanged += (o,e) =>
{ Console.WriteLine("New items: {0}", String.Join (",", e.NewItems.OfType<int>())); };
field_ = "";
}
Collection initializers are described in §7.6.10.3 of C# Language Specification