In local variables, with optimization turned on, the compiler will (at least sometimes) compile to code which first assigns to the variable, then calls Add (or sets properties, for object initializers).
If you use a static or an instance variable, you'll see different behaviour:
class Test
{
    static List<int> StaticList = new List<int> { 1 };
    List<int> InstanceList = new List<int> { 2 };
}
Gives the following type initializer IL:
.method private hidebysig specialname rtspecialname static 
        void  .cctor() cil managed
{
  // Code size       21 (0x15)
  .maxstack  2
  .locals init (class [mscorlib]System.Collections.Generic.List`1<int32> V_0)
  IL_0000:  newobj     instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
  IL_0005:  stloc.0
  IL_0006:  ldloc.0
  IL_0007:  ldc.i4.1
  IL_0008:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_000d:  nop
  IL_000e:  ldloc.0
  IL_000f:  stsfld     class [mscorlib]System.Collections.Generic.List`1<int32> Test::StaticList
  IL_0014:  ret
} // end of method Test::.cctor
And the following constructor IL:
.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  // Code size       29 (0x1d)
  .maxstack  3
  .locals init (class [mscorlib]System.Collections.Generic.List`1<int32> V_0)
  IL_0000:  ldarg.0
  IL_0001:  newobj     instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldc.i4.2
  IL_0009:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_000e:  nop
  IL_000f:  ldloc.0
  IL_0010:  stfld      class [mscorlib]System.Collections.Generic.List`1<int32> Test::InstanceList
  IL_0015:  ldarg.0
  IL_0016:  call       instance void [mscorlib]System.Object::.ctor()
  IL_001b:  nop
  IL_001c:  ret
} // end of method Test::.ctor
In both cases, the collection is populated before the field is set. Now that's not to say that there may not still be memory model issues, but it's not the same as the field being set to refer to an empty collection and then the Add call being made. From the perspective of the assigning thread, the assignment happens after the Add.
In general, both object initializer and collection initializer expressions are equivalent to constructing the object using a temporary variable - so in the case where you use it in an assignment, the property setters are all called before the assignment takes place.
However, I don't believe any special guarantees are given around visibility to other threads for object/collection initializers. I would suggest that you imagine what the code would look like if written out "long-hand" according to the specification, and then reason from there.
There are guarantees given for static initializers and constructors - but primarily within the Microsoft implementation of .NET rather than "general" guarantees (e.g. within the C# specification or the ECMA spec).