/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Emit/CodeGen/ObjectAndCollectionInitializerTests.cs
3 737 строк
104 KB
Jared Parsons
Move net451 test assets to net461 (#74766)
17 авг 2024, 19:21
Не верифицирован
17 авг 2024, 19:21
75b26a2
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System.Linq; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen { public class ObjectAndCollectionInitializerTests : EmitMetadataTestBase { #region "Object Initializer Tests" [Fact] public void ObjectInitializerTest_ClassType() { var source = @" public class MemberInitializerTest { public int x; public int y { get; set; } public static void Main() { var i = new MemberInitializerTest() { x = 1, y = 2 }; System.Console.WriteLine(i.x); System.Console.WriteLine(i.y); } } "; string expectedOutput = @"1 2"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("MemberInitializerTest.Main", @" { // Code size 41 (0x29) .maxstack 3 IL_0000: newobj ""MemberInitializerTest..ctor()"" IL_0005: dup IL_0006: ldc.i4.1 IL_0007: stfld ""int MemberInitializerTest.x"" IL_000c: dup IL_000d: ldc.i4.2 IL_000e: callvirt ""void MemberInitializerTest.y.set"" IL_0013: dup IL_0014: ldfld ""int MemberInitializerTest.x"" IL_0019: call ""void System.Console.WriteLine(int)"" IL_001e: callvirt ""int MemberInitializerTest.y.get"" IL_0023: call ""void System.Console.WriteLine(int)"" IL_0028: ret }"); } [Fact] public void ObjectInitializerTest_StructType() { var source = @" public struct MemberInitializerTest { public int x; public int y { get; set; } public static void Main() { var i = new MemberInitializerTest() { x = 1, y = 2 }; System.Console.WriteLine(i.x); System.Console.WriteLine(i.y); } } "; string expectedOutput = @"1 2"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("MemberInitializerTest.Main", @" { // Code size 50 (0x32) .maxstack 2 .locals init (MemberInitializerTest V_0, //i MemberInitializerTest V_1) IL_0000: ldloca.s V_1 IL_0002: initobj ""MemberInitializerTest"" IL_0008: ldloca.s V_1 IL_000a: ldc.i4.1 IL_000b: stfld ""int MemberInitializerTest.x"" IL_0010: ldloca.s V_1 IL_0012: ldc.i4.2 IL_0013: call ""void MemberInitializerTest.y.set"" IL_0018: ldloc.1 IL_0019: stloc.0 IL_001a: ldloc.0 IL_001b: ldfld ""int MemberInitializerTest.x"" IL_0020: call ""void System.Console.WriteLine(int)"" IL_0025: ldloca.s V_0 IL_0027: call ""readonly int MemberInitializerTest.y.get"" IL_002c: call ""void System.Console.WriteLine(int)"" IL_0031: ret }"); } [Fact] public void ObjectInitializerTest_TypeParameterType() { var source = @" public class Base { public Base() {} public int x; public int y { get; set; } public static void Main() { MemberInitializerTest<Base>.Goo(); } } public class MemberInitializerTest<T> where T: Base, new() { public static void Goo() { var i = new T() { x = 1, y = 2 }; System.Console.WriteLine(i.x); System.Console.WriteLine(i.y); } } "; string expectedOutput = @"1 2"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("MemberInitializerTest<T>.Goo", @" { // Code size 61 (0x3d) .maxstack 3 IL_0000: call ""T System.Activator.CreateInstance<T>()"" IL_0005: dup IL_0006: box ""T"" IL_000b: ldc.i4.1 IL_000c: stfld ""int Base.x"" IL_0011: dup IL_0012: box ""T"" IL_0017: ldc.i4.2 IL_0018: callvirt ""void Base.y.set"" IL_001d: dup IL_001e: box ""T"" IL_0023: ldfld ""int Base.x"" IL_0028: call ""void System.Console.WriteLine(int)"" IL_002d: box ""T"" IL_0032: callvirt ""int Base.y.get"" IL_0037: call ""void System.Console.WriteLine(int)"" IL_003c: ret }"); } [Fact] public void ObjectInitializerTest_TypeParameterType_InterfaceConstraint() { var source = @" using System; class MemberInitializerTest { static int Main() { Console.WriteLine(Goo<S>()); return 0; } static byte Goo<T>() where T : I, new() { var b = new T { X = 1 }; return b.X; } } interface I { byte X { get; set; } } struct S : I { public byte X { get; set; } } "; string expectedOutput = "1"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("MemberInitializerTest.Goo<T>", @" { // Code size 36 (0x24) .maxstack 2 .locals init (T V_0, //b T V_1) IL_0000: call ""T System.Activator.CreateInstance<T>()"" IL_0005: stloc.1 IL_0006: ldloca.s V_1 IL_0008: ldc.i4.1 IL_0009: constrained. ""T"" IL_000f: callvirt ""void I.X.set"" IL_0014: ldloc.1 IL_0015: stloc.0 IL_0016: ldloca.s V_0 IL_0018: constrained. ""T"" IL_001e: callvirt ""byte I.X.get"" IL_0023: ret }"); } [Fact] public void ObjectInitializerTest_NullableType() { var source = @" using System; class MemberInitializerTest { static int Main() { Console.WriteLine(Goo<S>().Value.ToString(System.Globalization.CultureInfo.InvariantCulture)); return 0; } static Decimal? Goo<T>() where T : I, new() { var b = new T { X = 1.1M }; return b.X; } } interface I { Decimal? X { get; set; } } struct S : I { public Decimal? X { get; set; } }"; string expectedOutput = "1.1"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("MemberInitializerTest.Goo<T>", @" { // Code size 51 (0x33) .maxstack 6 .locals init (T V_0, //b T V_1) IL_0000: call ""T System.Activator.CreateInstance<T>()"" IL_0005: stloc.1 IL_0006: ldloca.s V_1 IL_0008: ldc.i4.s 11 IL_000a: ldc.i4.0 IL_000b: ldc.i4.0 IL_000c: ldc.i4.0 IL_000d: ldc.i4.1 IL_000e: newobj ""decimal..ctor(int, int, int, bool, byte)"" IL_0013: newobj ""decimal?..ctor(decimal)"" IL_0018: constrained. ""T"" IL_001e: callvirt ""void I.X.set"" IL_0023: ldloc.1 IL_0024: stloc.0 IL_0025: ldloca.s V_0 IL_0027: constrained. ""T"" IL_002d: callvirt ""decimal? I.X.get"" IL_0032: ret }"); } [Fact] public void ObjectInitializerTest_AssignWriteOnlyProperty() { var source = @" public class MemberInitializerTest { public int x; public int Prop { set { x = value; } } public static void Main() { var i = new MemberInitializerTest() { Prop = 1 }; System.Console.WriteLine(i.x); } } "; string expectedOutput = "1"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("MemberInitializerTest.Main", @" { // Code size 23 (0x17) .maxstack 3 IL_0000: newobj ""MemberInitializerTest..ctor()"" IL_0005: dup IL_0006: ldc.i4.1 IL_0007: callvirt ""void MemberInitializerTest.Prop.set"" IL_000c: ldfld ""int MemberInitializerTest.x"" IL_0011: call ""void System.Console.WriteLine(int)"" IL_0016: ret }"); } [Fact] public void ObjectInitializerTest_AssignMembersOfReadOnlyField() { var source = @" public class MemberInitializerTest { public int x; public int y { get; set; } } public class Test { public readonly MemberInitializerTest m = new MemberInitializerTest(); public static void Main() { var i = new Test() { m = { x = 1, y = 2 } }; System.Console.WriteLine(i.m.x); System.Console.WriteLine(i.m.y); } } "; string expectedOutput = @"1 2"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 61 (0x3d) .maxstack 3 IL_0000: newobj ""Test..ctor()"" IL_0005: dup IL_0006: ldfld ""MemberInitializerTest Test.m"" IL_000b: ldc.i4.1 IL_000c: stfld ""int MemberInitializerTest.x"" IL_0011: dup IL_0012: ldfld ""MemberInitializerTest Test.m"" IL_0017: ldc.i4.2 IL_0018: callvirt ""void MemberInitializerTest.y.set"" IL_001d: dup IL_001e: ldfld ""MemberInitializerTest Test.m"" IL_0023: ldfld ""int MemberInitializerTest.x"" IL_0028: call ""void System.Console.WriteLine(int)"" IL_002d: ldfld ""MemberInitializerTest Test.m"" IL_0032: callvirt ""int MemberInitializerTest.y.get"" IL_0037: call ""void System.Console.WriteLine(int)"" IL_003c: ret }"); } [Fact] public void ObjectInitializerTest_AssignFieldWithSameNameAsLocal() { var source = @" public class MemberInitializerTest { public int x; public static void Main() { int x = 1; MemberInitializerTest m = new MemberInitializerTest() { x = x + 1 }; System.Console.WriteLine(x); System.Console.WriteLine(m.x); } } "; string expectedOutput = @"1 2"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("MemberInitializerTest.Main", @" { // Code size 33 (0x21) .maxstack 4 .locals init (int V_0) //x IL_0000: ldc.i4.1 IL_0001: stloc.0 IL_0002: newobj ""MemberInitializerTest..ctor()"" IL_0007: dup IL_0008: ldloc.0 IL_0009: ldc.i4.1 IL_000a: add IL_000b: stfld ""int MemberInitializerTest.x"" IL_0010: ldloc.0 IL_0011: call ""void System.Console.WriteLine(int)"" IL_0016: ldfld ""int MemberInitializerTest.x"" IL_001b: call ""void System.Console.WriteLine(int)"" IL_0020: ret }"); } [Fact] public void ObjectInitializerTest_AssignmentOrderingIsPreserved() { var source = @" public class MemberInitializerTest { public int x, y, z; public static void Main() { Goo(); } public static void Goo(MemberInitializerTest nullArg = null) { MemberInitializerTest m = new MemberInitializerTest() { x = -1, y = -1, z = -1 }; try { m = new MemberInitializerTest { x = Bar(1), y = nullArg.y, z = Bar(3) }; } catch(System.NullReferenceException) { } System.Console.WriteLine(m.x); System.Console.WriteLine(m.y); System.Console.WriteLine(m.z); } public static int Bar(int i) { System.Console.WriteLine(i); return i; } } "; string expectedOutput = @"1 -1 -1 -1"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("MemberInitializerTest.Goo", @" { // Code size 108 (0x6c) .maxstack 3 .locals init (MemberInitializerTest V_0) //m IL_0000: newobj ""MemberInitializerTest..ctor()"" IL_0005: dup IL_0006: ldc.i4.m1 IL_0007: stfld ""int MemberInitializerTest.x"" IL_000c: dup IL_000d: ldc.i4.m1 IL_000e: stfld ""int MemberInitializerTest.y"" IL_0013: dup IL_0014: ldc.i4.m1 IL_0015: stfld ""int MemberInitializerTest.z"" IL_001a: stloc.0 .try { IL_001b: newobj ""MemberInitializerTest..ctor()"" IL_0020: dup IL_0021: ldc.i4.1 IL_0022: call ""int MemberInitializerTest.Bar(int)"" IL_0027: stfld ""int MemberInitializerTest.x"" IL_002c: dup IL_002d: ldarg.0 IL_002e: ldfld ""int MemberInitializerTest.y"" IL_0033: stfld ""int MemberInitializerTest.y"" IL_0038: dup IL_0039: ldc.i4.3 IL_003a: call ""int MemberInitializerTest.Bar(int)"" IL_003f: stfld ""int MemberInitializerTest.z"" IL_0044: stloc.0 IL_0045: leave.s IL_004a } catch System.NullReferenceException { IL_0047: pop IL_0048: leave.s IL_004a } IL_004a: ldloc.0 IL_004b: ldfld ""int MemberInitializerTest.x"" IL_0050: call ""void System.Console.WriteLine(int)"" IL_0055: ldloc.0 IL_0056: ldfld ""int MemberInitializerTest.y"" IL_005b: call ""void System.Console.WriteLine(int)"" IL_0060: ldloc.0 IL_0061: ldfld ""int MemberInitializerTest.z"" IL_0066: call ""void System.Console.WriteLine(int)"" IL_006b: ret }"); } [Fact] public void ObjectInitializerTest_NestedObjectInitializerExpression() { var source = @" public class MemberInitializerTest { public int x; public int y { get; set; } } public class Test { public int x; public int y { get; set; } public MemberInitializerTest z; public static void Main() { var i = new Test() { x = 1, y = 2, z = new MemberInitializerTest() { x = 3, y = 4 } }; System.Console.WriteLine(i.x); System.Console.WriteLine(i.y); System.Console.WriteLine(i.z.x); System.Console.WriteLine(i.z.y); } } "; string expectedOutput = @"1 2 3 4"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 98 (0x62) .maxstack 5 IL_0000: newobj ""Test..ctor()"" IL_0005: dup IL_0006: ldc.i4.1 IL_0007: stfld ""int Test.x"" IL_000c: dup IL_000d: ldc.i4.2 IL_000e: callvirt ""void Test.y.set"" IL_0013: dup IL_0014: newobj ""MemberInitializerTest..ctor()"" IL_0019: dup IL_001a: ldc.i4.3 IL_001b: stfld ""int MemberInitializerTest.x"" IL_0020: dup IL_0021: ldc.i4.4 IL_0022: callvirt ""void MemberInitializerTest.y.set"" IL_0027: stfld ""MemberInitializerTest Test.z"" IL_002c: dup IL_002d: ldfld ""int Test.x"" IL_0032: call ""void System.Console.WriteLine(int)"" IL_0037: dup IL_0038: callvirt ""int Test.y.get"" IL_003d: call ""void System.Console.WriteLine(int)"" IL_0042: dup IL_0043: ldfld ""MemberInitializerTest Test.z"" IL_0048: ldfld ""int MemberInitializerTest.x"" IL_004d: call ""void System.Console.WriteLine(int)"" IL_0052: ldfld ""MemberInitializerTest Test.z"" IL_0057: callvirt ""int MemberInitializerTest.y.get"" IL_005c: call ""void System.Console.WriteLine(int)"" IL_0061: ret }"); } [Fact()] public void ObjectInitializerTest_NestedObjectInitializer_InitializerValue() { var source = @" public class MemberInitializerTest { public int x; public int y { get; set; } } public class Test { public int x; public int y { get; set; } public readonly MemberInitializerTest z = new MemberInitializerTest(); public static void Main() { var i = new Test() { x = 1, y = 2, z = { x = 3, y = 4 } }; System.Console.WriteLine(i.x); System.Console.WriteLine(i.y); System.Console.WriteLine(i.z.x); System.Console.WriteLine(i.z.y); } } "; string expectedOutput = @"1 2 3 4"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 97 (0x61) .maxstack 3 IL_0000: newobj ""Test..ctor()"" IL_0005: dup IL_0006: ldc.i4.1 IL_0007: stfld ""int Test.x"" IL_000c: dup IL_000d: ldc.i4.2 IL_000e: callvirt ""void Test.y.set"" IL_0013: dup IL_0014: ldfld ""MemberInitializerTest Test.z"" IL_0019: ldc.i4.3 IL_001a: stfld ""int MemberInitializerTest.x"" IL_001f: dup IL_0020: ldfld ""MemberInitializerTest Test.z"" IL_0025: ldc.i4.4 IL_0026: callvirt ""void MemberInitializerTest.y.set"" IL_002b: dup IL_002c: ldfld ""int Test.x"" IL_0031: call ""void System.Console.WriteLine(int)"" IL_0036: dup IL_0037: callvirt ""int Test.y.get"" IL_003c: call ""void System.Console.WriteLine(int)"" IL_0041: dup IL_0042: ldfld ""MemberInitializerTest Test.z"" IL_0047: ldfld ""int MemberInitializerTest.x"" IL_004c: call ""void System.Console.WriteLine(int)"" IL_0051: ldfld ""MemberInitializerTest Test.z"" IL_0056: callvirt ""int MemberInitializerTest.y.get"" IL_005b: call ""void System.Console.WriteLine(int)"" IL_0060: ret }"); } [Fact] public void ObjectInitializerTest_NestedCollectionInitializerExpression() { var source = @" using System; using System.Collections.Generic; public class MemberInitializerTest { public List<int> x = new List<int>(); public List<int> y { get { return x; } set { x = value; } } } public class Test { public List<int> x = new List<int>(); public List<int> y { get { return x; } set { x = value; } } public MemberInitializerTest z; public static void Main() { var i = new Test() { x = { 1 }, y = { 2 }, z = new MemberInitializerTest() { x = { 3 }, y = { 4 } } }; DisplayCollection(i.x); DisplayCollection(i.y); DisplayCollection(i.z.x); DisplayCollection(i.z.y); } public static void DisplayCollection<T>(IEnumerable<T> collection) { foreach (var i in collection) { Console.WriteLine(i); } } } "; string expectedOutput = @"1 2 1 2 3 4 3 4"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 118 (0x76) .maxstack 5 IL_0000: newobj ""Test..ctor()"" IL_0005: dup IL_0006: ldfld ""System.Collections.Generic.List<int> Test.x"" IL_000b: ldc.i4.1 IL_000c: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0011: dup IL_0012: callvirt ""System.Collections.Generic.List<int> Test.y.get"" IL_0017: ldc.i4.2 IL_0018: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_001d: dup IL_001e: newobj ""MemberInitializerTest..ctor()"" IL_0023: dup IL_0024: ldfld ""System.Collections.Generic.List<int> MemberInitializerTest.x"" IL_0029: ldc.i4.3 IL_002a: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_002f: dup IL_0030: callvirt ""System.Collections.Generic.List<int> MemberInitializerTest.y.get"" IL_0035: ldc.i4.4 IL_0036: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_003b: stfld ""MemberInitializerTest Test.z"" IL_0040: dup IL_0041: ldfld ""System.Collections.Generic.List<int> Test.x"" IL_0046: call ""void Test.DisplayCollection<int>(System.Collections.Generic.IEnumerable<int>)"" IL_004b: dup IL_004c: callvirt ""System.Collections.Generic.List<int> Test.y.get"" IL_0051: call ""void Test.DisplayCollection<int>(System.Collections.Generic.IEnumerable<int>)"" IL_0056: dup IL_0057: ldfld ""MemberInitializerTest Test.z"" IL_005c: ldfld ""System.Collections.Generic.List<int> MemberInitializerTest.x"" IL_0061: call ""void Test.DisplayCollection<int>(System.Collections.Generic.IEnumerable<int>)"" IL_0066: ldfld ""MemberInitializerTest Test.z"" IL_006b: callvirt ""System.Collections.Generic.List<int> MemberInitializerTest.y.get"" IL_0070: call ""void Test.DisplayCollection<int>(System.Collections.Generic.IEnumerable<int>)"" IL_0075: ret }"); } [Fact] public void ObjectInitializerTest_NestedCollectionInitializer_InitializerValue() { var source = @" using System; using System.Collections.Generic; public class MemberInitializerTest { public List<int> x = new List<int>(); public List<int> y { get { return x; } set { x = value; } } } public class Test { public List<int> x = new List<int>(); public List<int> y { get { return x; } set { x = value; } } public MemberInitializerTest z = new MemberInitializerTest(); public static void Main() { var i = new Test() { x = { 1 }, y = { 2 }, z = { x = { 3 }, y = { 4 } } }; DisplayCollection(i.x); DisplayCollection(i.y); DisplayCollection(i.z.x); DisplayCollection(i.z.y); } public static void DisplayCollection<T>(IEnumerable<T> collection) { foreach (var i in collection) { Console.WriteLine(i); } } } "; string expectedOutput = @"1 2 1 2 3 4 3 4"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 117 (0x75) .maxstack 3 IL_0000: newobj ""Test..ctor()"" IL_0005: dup IL_0006: ldfld ""System.Collections.Generic.List<int> Test.x"" IL_000b: ldc.i4.1 IL_000c: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0011: dup IL_0012: callvirt ""System.Collections.Generic.List<int> Test.y.get"" IL_0017: ldc.i4.2 IL_0018: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_001d: dup IL_001e: ldfld ""MemberInitializerTest Test.z"" IL_0023: ldfld ""System.Collections.Generic.List<int> MemberInitializerTest.x"" IL_0028: ldc.i4.3 IL_0029: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_002e: dup IL_002f: ldfld ""MemberInitializerTest Test.z"" IL_0034: callvirt ""System.Collections.Generic.List<int> MemberInitializerTest.y.get"" IL_0039: ldc.i4.4 IL_003a: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_003f: dup IL_0040: ldfld ""System.Collections.Generic.List<int> Test.x"" IL_0045: call ""void Test.DisplayCollection<int>(System.Collections.Generic.IEnumerable<int>)"" IL_004a: dup IL_004b: callvirt ""System.Collections.Generic.List<int> Test.y.get"" IL_0050: call ""void Test.DisplayCollection<int>(System.Collections.Generic.IEnumerable<int>)"" IL_0055: dup IL_0056: ldfld ""MemberInitializerTest Test.z"" IL_005b: ldfld ""System.Collections.Generic.List<int> MemberInitializerTest.x"" IL_0060: call ""void Test.DisplayCollection<int>(System.Collections.Generic.IEnumerable<int>)"" IL_0065: ldfld ""MemberInitializerTest Test.z"" IL_006a: callvirt ""System.Collections.Generic.List<int> MemberInitializerTest.y.get"" IL_006f: call ""void Test.DisplayCollection<int>(System.Collections.Generic.IEnumerable<int>)"" IL_0074: ret }"); } [WorkItem(2021, "https://devdiv.visualstudio.com:443/defaultcollection/DevDiv/_workitems/edit/2021")] [Fact()] public void ObjectInitializerFieldlikeEvent() { var source = @" public delegate void D(); public struct MemberInitializerTest { public event D z; public static void Main() { var i = new MemberInitializerTest() { z = null }; } }"; var compVerifier = CompileAndVerify(source, expectedOutput: ""); compVerifier.VerifyIL("MemberInitializerTest.Main", @" { // Code size 17 (0x11) .maxstack 2 .locals init (MemberInitializerTest V_0) IL_0000: ldloca.s V_0 IL_0002: initobj ""MemberInitializerTest"" IL_0008: ldloca.s V_0 IL_000a: ldnull IL_000b: stfld ""D MemberInitializerTest.z"" IL_0010: ret }"); } [Fact] public void ObjectInitializerTest_UseVariableBeingAssignedInObjectInitializer() { var source = @" public class Test { public int x, y; public static void Main() { Test m = new Test() { x = Goo(out m), y = m.x }; System.Console.WriteLine(m.x); // Print 1 System.Console.WriteLine(m.y); // Print 0 } public static int Goo(out Test m) { m = new Test() { x = 0 }; return 1; } } "; string expectedOutput = @"1 0"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 54 (0x36) .maxstack 3 .locals init (Test V_0) //m IL_0000: newobj ""Test..ctor()"" IL_0005: dup IL_0006: ldloca.s V_0 IL_0008: call ""int Test.Goo(out Test)"" IL_000d: stfld ""int Test.x"" IL_0012: dup IL_0013: ldloc.0 IL_0014: ldfld ""int Test.x"" IL_0019: stfld ""int Test.y"" IL_001e: stloc.0 IL_001f: ldloc.0 IL_0020: ldfld ""int Test.x"" IL_0025: call ""void System.Console.WriteLine(int)"" IL_002a: ldloc.0 IL_002b: ldfld ""int Test.y"" IL_0030: call ""void System.Console.WriteLine(int)"" IL_0035: ret }"); } [Fact] public void DictionaryInitializerTest001() { var source = @" using System.Collections.Generic; class Program { static void Main(string[] args) { var x = new Dictionary<string, int>() {[""aaa""] = 3}; System.Console.WriteLine(x[""aaa""]); } } "; string expectedOutput = @"3"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Program.Main", @" { // Code size 33 (0x21) .maxstack 4 IL_0000: newobj ""System.Collections.Generic.Dictionary<string, int>..ctor()"" IL_0005: dup IL_0006: ldstr ""aaa"" IL_000b: ldc.i4.3 IL_000c: callvirt ""void System.Collections.Generic.Dictionary<string, int>.this[string].set"" IL_0011: ldstr ""aaa"" IL_0016: callvirt ""int System.Collections.Generic.Dictionary<string, int>.this[string].get"" IL_001b: call ""void System.Console.WriteLine(int)"" IL_0020: ret } "); } [Fact] public void DictionaryInitializerTestSideeffects001() { var source = @" using System; class A { A this[int x] { get { Console.WriteLine(x); return new A(); } } int X, Y, Z; static void Main() { int x = 1; new A {[x: x++] = { X = 1, Y = 1, Z = 1 } }; Console.WriteLine('-'); new A {[x++] = { } }; Console.WriteLine('-'); Console.WriteLine(x); } } "; string expectedOutput = @" 1 1 1 - - 3"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("A.Main()", @" { // Code size 84 (0x54) .maxstack 3 .locals init (int V_0, //x A V_1, int V_2) IL_0000: ldc.i4.1 IL_0001: stloc.0 IL_0002: newobj ""A..ctor()"" IL_0007: stloc.1 IL_0008: ldloc.0 IL_0009: dup IL_000a: ldc.i4.1 IL_000b: add IL_000c: stloc.0 IL_000d: stloc.2 IL_000e: ldloc.1 IL_000f: ldloc.2 IL_0010: callvirt ""A A.this[int].get"" IL_0015: ldc.i4.1 IL_0016: stfld ""int A.X"" IL_001b: ldloc.1 IL_001c: ldloc.2 IL_001d: callvirt ""A A.this[int].get"" IL_0022: ldc.i4.1 IL_0023: stfld ""int A.Y"" IL_0028: ldloc.1 IL_0029: ldloc.2 IL_002a: callvirt ""A A.this[int].get"" IL_002f: ldc.i4.1 IL_0030: stfld ""int A.Z"" IL_0035: ldc.i4.s 45 IL_0037: call ""void System.Console.WriteLine(char)"" IL_003c: newobj ""A..ctor()"" IL_0041: pop IL_0042: ldloc.0 IL_0043: ldc.i4.1 IL_0044: add IL_0045: stloc.0 IL_0046: ldc.i4.s 45 IL_0048: call ""void System.Console.WriteLine(char)"" IL_004d: ldloc.0 IL_004e: call ""void System.Console.WriteLine(int)"" IL_0053: ret } "); } [Fact] public void DictionaryInitializerTestSideeffects001param() { var source = @" using System; class A { A this[params int[] x] { get { Console.WriteLine(x[0]); x[0] = 12345; return new A(); } } int X, Y, Z; static void Main() { int x = 1; new A {[x++] = { X = 1, Y = 1, Z = 1 } }; Console.WriteLine('-'); new A {[x++] = { } }; Console.WriteLine('-'); Console.WriteLine(x); } } "; string expectedOutput = @" 1 1 1 - - 3"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("A.Main()", @" { // Code size 111 (0x6f) .maxstack 5 .locals init (int V_0, //x A V_1, int V_2) IL_0000: ldc.i4.1 IL_0001: stloc.0 IL_0002: newobj ""A..ctor()"" IL_0007: stloc.1 IL_0008: ldloc.0 IL_0009: dup IL_000a: ldc.i4.1 IL_000b: add IL_000c: stloc.0 IL_000d: stloc.2 IL_000e: ldloc.1 IL_000f: ldc.i4.1 IL_0010: newarr ""int"" IL_0015: dup IL_0016: ldc.i4.0 IL_0017: ldloc.2 IL_0018: stelem.i4 IL_0019: callvirt ""A A.this[params int[]].get"" IL_001e: ldc.i4.1 IL_001f: stfld ""int A.X"" IL_0024: ldloc.1 IL_0025: ldc.i4.1 IL_0026: newarr ""int"" IL_002b: dup IL_002c: ldc.i4.0 IL_002d: ldloc.2 IL_002e: stelem.i4 IL_002f: callvirt ""A A.this[params int[]].get"" IL_0034: ldc.i4.1 IL_0035: stfld ""int A.Y"" IL_003a: ldloc.1 IL_003b: ldc.i4.1 IL_003c: newarr ""int"" IL_0041: dup IL_0042: ldc.i4.0 IL_0043: ldloc.2 IL_0044: stelem.i4 IL_0045: callvirt ""A A.this[params int[]].get"" IL_004a: ldc.i4.1 IL_004b: stfld ""int A.Z"" IL_0050: ldc.i4.s 45 IL_0052: call ""void System.Console.WriteLine(char)"" IL_0057: newobj ""A..ctor()"" IL_005c: pop IL_005d: ldloc.0 IL_005e: ldc.i4.1 IL_005f: add IL_0060: stloc.0 IL_0061: ldc.i4.s 45 IL_0063: call ""void System.Console.WriteLine(char)"" IL_0068: ldloc.0 IL_0069: call ""void System.Console.WriteLine(int)"" IL_006e: ret } "); var comp = compVerifier.Compilation; var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var node = tree.GetRoot().DescendantNodes().OfType<Syntax.ObjectCreationExpressionSyntax>().Last(); Assert.Equal("new A {[x++] = { } }", node.ToString()); var (graph, symbol) = ControlFlowGraphVerifier.GetControlFlowGraph(node.Parent.Parent, model); ControlFlowGraphVerifier.VerifyGraph(comp, """ Block[B0] - Entry Statements (0) Next (Regular) Block[B1] Entering: {R1} .locals {R1} { Locals: [System.Int32 x] Block[B1] - Block Predecessors: [B0] Statements (1) ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x = 1') Left: ILocalReferenceOperation: x (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsImplicit) (Syntax: 'x = 1') Right: ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') Next (Regular) Block[B2] Entering: {R2} .locals {R2} { CaptureIds: [0] Block[B2] - Block Predecessors: [B1] Statements (1) IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'new A {[x++ ... , Z = 1 } }') Value: IObjectCreationOperation (Constructor: A..ctor()) (OperationKind.ObjectCreation, Type: A) (Syntax: 'new A {[x++ ... , Z = 1 } }') Arguments(0) Initializer: null Next (Regular) Block[B3] Entering: {R3} .locals {R3} { CaptureIds: [1] Block[B3] - Block Predecessors: [B2] Statements (4) IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: '[x++]') Value: IArrayCreationOperation (OperationKind.ArrayCreation, Type: System.Int32[], IsImplicit) (Syntax: '[x++]') Dimension Sizes(1): ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsImplicit) (Syntax: '[x++]') Initializer: IArrayInitializerOperation (1 elements) (OperationKind.ArrayInitializer, Type: null, IsImplicit) (Syntax: '[x++]') Element Values(1): IIncrementOrDecrementOperation (Postfix) (OperationKind.Increment, Type: System.Int32) (Syntax: 'x++') Target: ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x') ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: 'X = 1') Left: IFieldReferenceOperation: System.Int32 A.X (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'X') Instance Receiver: IPropertyReferenceOperation: A A.this[params System.Int32[] x] { get; } (OperationKind.PropertyReference, Type: A) (Syntax: '[x++]') Instance Receiver: IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: A, IsImplicit) (Syntax: 'new A {[x++ ... , Z = 1 } }') Arguments(1): IArgumentOperation (ArgumentKind.ParamArray, Matching Parameter: x) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: '[x++]') IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32[], IsImplicit) (Syntax: '[x++]') InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Right: ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: 'Y = 1') Left: IFieldReferenceOperation: System.Int32 A.Y (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'Y') Instance Receiver: IPropertyReferenceOperation: A A.this[params System.Int32[] x] { get; } (OperationKind.PropertyReference, Type: A) (Syntax: '[x++]') Instance Receiver: IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: A, IsImplicit) (Syntax: 'new A {[x++ ... , Z = 1 } }') Arguments(1): IArgumentOperation (ArgumentKind.ParamArray, Matching Parameter: x) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: '[x++]') IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32[], IsImplicit) (Syntax: '[x++]') InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Right: ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: 'Z = 1') Left: IFieldReferenceOperation: System.Int32 A.Z (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'Z') Instance Receiver: IPropertyReferenceOperation: A A.this[params System.Int32[] x] { get; } (OperationKind.PropertyReference, Type: A) (Syntax: '[x++]') Instance Receiver: IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: A, IsImplicit) (Syntax: 'new A {[x++ ... , Z = 1 } }') Arguments(1): IArgumentOperation (ArgumentKind.ParamArray, Matching Parameter: x) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: '[x++]') IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32[], IsImplicit) (Syntax: '[x++]') InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Right: ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') Next (Regular) Block[B4] Leaving: {R3} } Block[B4] - Block Predecessors: [B3] Statements (1) IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'new A {[x++ ... Z = 1 } };') Expression: IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: A, IsImplicit) (Syntax: 'new A {[x++ ... , Z = 1 } }') Next (Regular) Block[B5] Leaving: {R2} } Block[B5] - Block Predecessors: [B4] Statements (1) IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'Console.WriteLine('-');') Expression: IInvocationOperation (void System.Console.WriteLine(System.Char value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'Console.WriteLine('-')') Instance Receiver: null Arguments(1): IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: ''-'') ILiteralOperation (OperationKind.Literal, Type: System.Char, Constant: -) (Syntax: ''-'') InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Next (Regular) Block[B6] Entering: {R4} .locals {R4} { CaptureIds: [2] Block[B6] - Block Predecessors: [B5] Statements (3) IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'new A {[x++] = { } }') Value: IObjectCreationOperation (Constructor: A..ctor()) (OperationKind.ObjectCreation, Type: A) (Syntax: 'new A {[x++] = { } }') Arguments(0) Initializer: null IIncrementOrDecrementOperation (Postfix) (OperationKind.Increment, Type: System.Int32) (Syntax: 'x++') Target: ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'new A {[x++] = { } };') Expression: IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: A, IsImplicit) (Syntax: 'new A {[x++] = { } }') Next (Regular) Block[B7] Leaving: {R4} } Block[B7] - Block Predecessors: [B6] Statements (2) IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'Console.WriteLine('-');') Expression: IInvocationOperation (void System.Console.WriteLine(System.Char value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'Console.WriteLine('-')') Instance Receiver: null Arguments(1): IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: ''-'') ILiteralOperation (OperationKind.Literal, Type: System.Char, Constant: -) (Syntax: ''-'') InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'Console.WriteLine(x);') Expression: IInvocationOperation (void System.Console.WriteLine(System.Int32 value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'Console.WriteLine(x)') Instance Receiver: null Arguments(1): IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: 'x') ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x') InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Next (Regular) Block[B8] Leaving: {R1} } Block[B8] - Exit Predecessors: [B7] Statements (0) """, graph, symbol); } [Fact] public void DictionaryInitializerTestSideeffects001named() { var source = @" using System; class A { A this[int x, int y] { get { Console.WriteLine(x); Console.WriteLine(y); return new A(); } } int X, Y, Z; static void Main() { int x = 1; new A {[y: x++, x: x++] = { X = 1, Y = 1, Z = 1 } }; Console.WriteLine('-'); new A {[y: x++, x: x++] = { } }; Console.WriteLine('-'); Console.WriteLine(x); } } "; string expectedOutput = @" 2 1 2 1 2 1 - - 5"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); } [Fact] public void DictionaryInitializerTestSideeffects001namedAsync() { var source = @" using System; using System.Threading.Tasks; class A { A this[int x, int y] { get { Console.WriteLine(x); Console.WriteLine(y); return new A(); } } int X, Y, Z; static void Main() { Test().Wait(); } private static async Task<int> Test() { int x = 1; new A {[y: await F(x++), x: await F(x++)] = { X = 1, Y = await F(1), Z = 1 } }; Console.WriteLine('-'); new A {[y: x++, x: x++] = { } }; Console.WriteLine('-'); Console.WriteLine(x); return 42; } private static async Task<int> F(int x) { await Task.Yield(); return x; } } "; string expectedOutput = @" 2 1 2 1 2 1 - - 5"; var comp = CreateCompilationWithMscorlib461AndCSharp(source, options: TestOptions.ReleaseExe); CompileAndVerify(comp, expectedOutput: expectedOutput); } [Fact] public void DictionaryInitializerTestSideeffects001dyn() { var source = @" using System; class A { dynamic this[int x] { get { Console.WriteLine(x); return new A(); } } int X, Y, Z; static void Main() { int x = 1; new A {[x++] = { X = 1, Y = 1, Z = 1 } }; Console.WriteLine('-'); new A {[x++] = { } }; Console.WriteLine('-'); Console.WriteLine(x); } } "; string expectedOutput = @" 1 1 1 - - 3"; CompileAndVerify(source, targetFramework: TargetFramework.StandardAndCSharp, expectedOutput: expectedOutput); } [Fact] public void DictionaryInitializerTestSideeffects001namedDynamic() { var source = @" using System; class A { dynamic this[int x, int y] { get { Console.WriteLine(x); Console.WriteLine(y); return new A(); } } dynamic this[string x, string y] { get { throw null; } } int X, Y, Z; static void Main() { dynamic x = 1; new A {[y: x++, x: x++] = { X = 1, Y = 1, Z = 1 } }; Console.WriteLine('-'); new A {[y: x++, x: x++] = { } }; Console.WriteLine('-'); Console.WriteLine(x); } } "; string expectedOutput = @" 2 1 2 1 2 1 - - 5"; var comp = CreateCompilationWithMscorlib461AndCSharp(source, options: TestOptions.ReleaseExe); CompileAndVerify(comp, expectedOutput: expectedOutput); } [Fact] public void DictionaryInitializerTestSideeffects001a() { var source = @" using System; struct A { public A[] arr; int X, Y, Z; public A(int x) { X = 0; Y = 0; Z = 0; arr = new A[x]; } static void Main() { int x = 1; var v = new A(3) {arr = {[x++] = { X = 1, Y = x, Z = 3 },[x++] = { X = 1, Y = x, Z = 3 }} }; System.Console.WriteLine(v.arr[0].Y); System.Console.WriteLine(v.arr[1].Y); System.Console.WriteLine(v.arr[2].Y); } } "; string expectedOutput = @" 0 2 3"; var compVerifier = CompileAndVerify(source, references: new[] { CSharpRef }, expectedOutput: expectedOutput); compVerifier.VerifyIL("A.Main()", @" { // Code size 194 (0xc2) .maxstack 4 .locals init (int V_0, //x int V_1, int V_2) IL_0000: ldc.i4.1 IL_0001: stloc.0 IL_0002: ldc.i4.3 IL_0003: newobj ""A..ctor(int)"" IL_0008: ldloc.0 IL_0009: dup IL_000a: ldc.i4.1 IL_000b: add IL_000c: stloc.0 IL_000d: stloc.1 IL_000e: dup IL_000f: ldfld ""A[] A.arr"" IL_0014: ldloc.1 IL_0015: ldelema ""A"" IL_001a: ldc.i4.1 IL_001b: stfld ""int A.X"" IL_0020: dup IL_0021: ldfld ""A[] A.arr"" IL_0026: ldloc.1 IL_0027: ldelema ""A"" IL_002c: ldloc.0 IL_002d: stfld ""int A.Y"" IL_0032: dup IL_0033: ldfld ""A[] A.arr"" IL_0038: ldloc.1 IL_0039: ldelema ""A"" IL_003e: ldc.i4.3 IL_003f: stfld ""int A.Z"" IL_0044: ldloc.0 IL_0045: dup IL_0046: ldc.i4.1 IL_0047: add IL_0048: stloc.0 IL_0049: stloc.2 IL_004a: dup IL_004b: ldfld ""A[] A.arr"" IL_0050: ldloc.2 IL_0051: ldelema ""A"" IL_0056: ldc.i4.1 IL_0057: stfld ""int A.X"" IL_005c: dup IL_005d: ldfld ""A[] A.arr"" IL_0062: ldloc.2 IL_0063: ldelema ""A"" IL_0068: ldloc.0 IL_0069: stfld ""int A.Y"" IL_006e: dup IL_006f: ldfld ""A[] A.arr"" IL_0074: ldloc.2 IL_0075: ldelema ""A"" IL_007a: ldc.i4.3 IL_007b: stfld ""int A.Z"" IL_0080: dup IL_0081: ldfld ""A[] A.arr"" IL_0086: ldc.i4.0 IL_0087: ldelema ""A"" IL_008c: ldfld ""int A.Y"" IL_0091: call ""void System.Console.WriteLine(int)"" IL_0096: dup IL_0097: ldfld ""A[] A.arr"" IL_009c: ldc.i4.1 IL_009d: ldelema ""A"" IL_00a2: ldfld ""int A.Y"" IL_00a7: call ""void System.Console.WriteLine(int)"" IL_00ac: ldfld ""A[] A.arr"" IL_00b1: ldc.i4.2 IL_00b2: ldelema ""A"" IL_00b7: ldfld ""int A.Y"" IL_00bc: call ""void System.Console.WriteLine(int)"" IL_00c1: ret } "); } [Fact] public void DictionaryInitializerTestSideeffects001a1() { var source = @" using System; struct A { private A[] _arr; public A[] arr { get { System.Console.WriteLine(""get""); return _arr; } } int X, Y, Z; public A(int x) { X = 0; Y = 0; Z = 0; _arr = new A[x]; } static void Main() { int x = 1; var v = new A(3) {arr = {[x++] = { X = 1, Y = x, Z = 3 },[x++] = { X = 1, Y = x, Z = 3 }} }; System.Console.WriteLine(""=======""); System.Console.WriteLine(v.arr[0].Y); System.Console.WriteLine(v.arr[1].Y); System.Console.WriteLine(v.arr[2].Y); } } "; string expectedOutput = @" get get get get get get ======= get 0 get 2 get 3"; var compVerifier = CompileAndVerify(source, references: new[] { CSharpRef }, expectedOutput: expectedOutput); compVerifier.VerifyIL("A.Main()", @" { // Code size 222 (0xde) .maxstack 3 .locals init (int V_0, //x A V_1, //v A V_2, int V_3, int V_4) IL_0000: ldc.i4.1 IL_0001: stloc.0 IL_0002: ldloca.s V_2 IL_0004: ldc.i4.3 IL_0005: call ""A..ctor(int)"" IL_000a: ldloc.0 IL_000b: dup IL_000c: ldc.i4.1 IL_000d: add IL_000e: stloc.0 IL_000f: stloc.3 IL_0010: ldloca.s V_2 IL_0012: call ""A[] A.arr.get"" IL_0017: ldloc.3 IL_0018: ldelema ""A"" IL_001d: ldc.i4.1 IL_001e: stfld ""int A.X"" IL_0023: ldloca.s V_2 IL_0025: call ""A[] A.arr.get"" IL_002a: ldloc.3 IL_002b: ldelema ""A"" IL_0030: ldloc.0 IL_0031: stfld ""int A.Y"" IL_0036: ldloca.s V_2 IL_0038: call ""A[] A.arr.get"" IL_003d: ldloc.3 IL_003e: ldelema ""A"" IL_0043: ldc.i4.3 IL_0044: stfld ""int A.Z"" IL_0049: ldloc.0 IL_004a: dup IL_004b: ldc.i4.1 IL_004c: add IL_004d: stloc.0 IL_004e: stloc.s V_4 IL_0050: ldloca.s V_2 IL_0052: call ""A[] A.arr.get"" IL_0057: ldloc.s V_4 IL_0059: ldelema ""A"" IL_005e: ldc.i4.1 IL_005f: stfld ""int A.X"" IL_0064: ldloca.s V_2 IL_0066: call ""A[] A.arr.get"" IL_006b: ldloc.s V_4 IL_006d: ldelema ""A"" IL_0072: ldloc.0 IL_0073: stfld ""int A.Y"" IL_0078: ldloca.s V_2 IL_007a: call ""A[] A.arr.get"" IL_007f: ldloc.s V_4 IL_0081: ldelema ""A"" IL_0086: ldc.i4.3 IL_0087: stfld ""int A.Z"" IL_008c: ldloc.2 IL_008d: stloc.1 IL_008e: ldstr ""======="" IL_0093: call ""void System.Console.WriteLine(string)"" IL_0098: ldloca.s V_1 IL_009a: call ""A[] A.arr.get"" IL_009f: ldc.i4.0 IL_00a0: ldelema ""A"" IL_00a5: ldfld ""int A.Y"" IL_00aa: call ""void System.Console.WriteLine(int)"" IL_00af: ldloca.s V_1 IL_00b1: call ""A[] A.arr.get"" IL_00b6: ldc.i4.1 IL_00b7: ldelema ""A"" IL_00bc: ldfld ""int A.Y"" IL_00c1: call ""void System.Console.WriteLine(int)"" IL_00c6: ldloca.s V_1 IL_00c8: call ""A[] A.arr.get"" IL_00cd: ldc.i4.2 IL_00ce: ldelema ""A"" IL_00d3: ldfld ""int A.Y"" IL_00d8: call ""void System.Console.WriteLine(int)"" IL_00dd: ret } "); } [Fact] public void DictionaryInitializerTestSideeffects001async() { var source = @" using System; using System.Threading.Tasks; struct A { private A[] _arr; public A[] arr { get { System.Console.WriteLine(""get""); return _arr; } } int X, Y, Z; public A(int x) { X = 0; Y = 0; Z = 0; _arr = new A[x]; } static void Main() { Test().Wait(); } private static async Task<int> Test() { int x = 1; var v = new A(3) { arr = {[x++] = { X = 1, Y = await F(x), Z = 3 },[await F(x++)] = { X = 1, Y = x, Z = await F(3) } } }; System.Console.WriteLine(""=======""); System.Console.WriteLine(v.arr[0].Y); System.Console.WriteLine(v.arr[1].Y); System.Console.WriteLine(v.arr[2].Y); return 42; } private static async Task<int> F(int x) { await Task.Yield(); return x; } } "; string expectedOutput = @" get get get get get get ======= get 0 get 2 get 3"; var comp = CreateCompilationWithMscorlib461AndCSharp(source, options: TestOptions.ReleaseExe); CompileAndVerify(comp, expectedOutput: expectedOutput); } [Fact] public void DictionaryInitializerTestSideeffects002() { var source = @" using System; class A { A this[int x, int y] { get { Console.Write(x); Console.WriteLine(y); return new A(); } } A this[int x, int y, int z] { get { Console.Write(x); Console.Write(y); Console.WriteLine(z); return new A(); } } int X, Y, Z; static void Main() { int x = 1; new A {[x++, 5] = { X = 1, Y = 1, Z = 1 } , [x++, 7, x++] = { X = 1, Y = 1, Z = 1 } }; Console.WriteLine(x); } } "; string expectedOutput = @" 15 15 15 273 273 273 4"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("A.Main()", @" { // Code size 118 (0x76) .maxstack 5 .locals init (int V_0, //x int V_1, int V_2, int V_3) IL_0000: ldc.i4.1 IL_0001: stloc.0 IL_0002: newobj ""A..ctor()"" IL_0007: ldloc.0 IL_0008: dup IL_0009: ldc.i4.1 IL_000a: add IL_000b: stloc.0 IL_000c: stloc.1 IL_000d: dup IL_000e: ldloc.1 IL_000f: ldc.i4.5 IL_0010: callvirt ""A A.this[int, int].get"" IL_0015: ldc.i4.1 IL_0016: stfld ""int A.X"" IL_001b: dup IL_001c: ldloc.1 IL_001d: ldc.i4.5 IL_001e: callvirt ""A A.this[int, int].get"" IL_0023: ldc.i4.1 IL_0024: stfld ""int A.Y"" IL_0029: dup IL_002a: ldloc.1 IL_002b: ldc.i4.5 IL_002c: callvirt ""A A.this[int, int].get"" IL_0031: ldc.i4.1 IL_0032: stfld ""int A.Z"" IL_0037: ldloc.0 IL_0038: dup IL_0039: ldc.i4.1 IL_003a: add IL_003b: stloc.0 IL_003c: stloc.2 IL_003d: ldloc.0 IL_003e: dup IL_003f: ldc.i4.1 IL_0040: add IL_0041: stloc.0 IL_0042: stloc.3 IL_0043: dup IL_0044: ldloc.2 IL_0045: ldc.i4.7 IL_0046: ldloc.3 IL_0047: callvirt ""A A.this[int, int, int].get"" IL_004c: ldc.i4.1 IL_004d: stfld ""int A.X"" IL_0052: dup IL_0053: ldloc.2 IL_0054: ldc.i4.7 IL_0055: ldloc.3 IL_0056: callvirt ""A A.this[int, int, int].get"" IL_005b: ldc.i4.1 IL_005c: stfld ""int A.Y"" IL_0061: ldloc.2 IL_0062: ldc.i4.7 IL_0063: ldloc.3 IL_0064: callvirt ""A A.this[int, int, int].get"" IL_0069: ldc.i4.1 IL_006a: stfld ""int A.Z"" IL_006f: ldloc.0 IL_0070: call ""void System.Console.WriteLine(int)"" IL_0075: ret } "); } [Fact] public void DictionaryInitializerTest002() { var source = @" using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; class Program { static void Main(string[] args) { var l = new cls1() { [""aaa""] = { 1, 2 }, [""bbb""] = { 42 } }; System.Console.Write(l[""bbb""][0]); System.Console.Write(l[""aaa""][1]); } class cls1 { private Dictionary<string, List<int>> dict = new Dictionary<string, List<int>>(); public dynamic this[string value] { get { List<int> member; if (dict.TryGetValue(value, out member)) { return member; } return dict[value] = new List<int>(); } } } } "; string expectedOutput = @"422"; var compVerifier = CompileAndVerify(source, targetFramework: TargetFramework.StandardAndCSharp, expectedOutput: expectedOutput); } [Fact] public void DictionaryInitializerTest003() { var source = @" using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; class Program { static void Main(string[] args) { var l = new Cls1() { [""aaa""] = { [""x""] = 1, [""y""] = 2 }, [""bbb""] = { [""z""] = 42 } }; System.Console.Write(l[""bbb""][""z""]); System.Console.Write(l[""aaa""][""y""]); } class Cls1 { private Dictionary<string, Dictionary<string, int>> dict = new Dictionary<string, Dictionary<string, int>>(); public Dictionary<string, int> this[string arg] { get { Dictionary<string, int> member; if (dict.TryGetValue(arg, out member)) { return member; } return dict[arg] = new Dictionary<string, int>(); } } } } "; string expectedOutput = @"422"; var compVerifier = CompileAndVerify(source, references: new[] { CSharpRef }, expectedOutput: expectedOutput); } [Fact] public void DictionaryInitializerTest004() { var source = @" using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; class Program { static void Main(string[] args) { var l = new Cls1() { [""aaa""] = { [""x""] = 1, [""y""] = 2 }, [""bbb""] = { [""z""] = 42 } }; System.Console.Write(l[""bbb""][""z""]); System.Console.Write(l[""aaa""][""y""]); } class Cls1 { private Dictionary<string, Dictionary<string, int>> dict = new Dictionary<string, Dictionary<string, int>>(); public dynamic this[string arg] { get { Dictionary<string, int> member; if (dict.TryGetValue(arg, out member)) { return member; } return dict[arg] = new Dictionary<string, int>(); } } } } "; string expectedOutput = @"422"; var compVerifier = CompileAndVerify(source, targetFramework: TargetFramework.StandardAndCSharp, expectedOutput: expectedOutput); } [Fact, WorkItem(1073330, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1073330")] public void NestedIndexerInitializerArray() { var source = @" class C { int[] a = new int[2]; static void Main() { var a = new C { a = { [0] = 1, [1] = 2 } }; System.Console.Write(""{0} {1}"", a.a[0], a.a[1]); } } "; CompileAndVerify(source, expectedOutput: "1 2").VerifyIL("C.Main", @" { // Code size 61 (0x3d) .maxstack 4 .locals init (C V_0) //a IL_0000: newobj ""C..ctor()"" IL_0005: dup IL_0006: ldfld ""int[] C.a"" IL_000b: ldc.i4.0 IL_000c: ldc.i4.1 IL_000d: stelem.i4 IL_000e: dup IL_000f: ldfld ""int[] C.a"" IL_0014: ldc.i4.1 IL_0015: ldc.i4.2 IL_0016: stelem.i4 IL_0017: stloc.0 IL_0018: ldstr ""{0} {1}"" IL_001d: ldloc.0 IL_001e: ldfld ""int[] C.a"" IL_0023: ldc.i4.0 IL_0024: ldelem.i4 IL_0025: box ""int"" IL_002a: ldloc.0 IL_002b: ldfld ""int[] C.a"" IL_0030: ldc.i4.1 IL_0031: ldelem.i4 IL_0032: box ""int"" IL_0037: call ""void System.Console.Write(string, object, object)"" IL_003c: ret }"); } [Fact, WorkItem(1073330, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1073330")] public void NestedIndexerInitializerMDArray() { var source = @" class C { int[,] a = new int[2,2]; static void Main() { var a = new C { a = { [0, 0] = 1, [0, 1] = 2, [1, 0] = 3, [1, 1] = 4} }; System.Console.Write(""{0} {1} {2} {3}"", a.a[0, 0], a.a[0, 1], a.a[1, 0], a.a[1, 1]); } } "; CompileAndVerify(source, expectedOutput: "1 2 3 4").VerifyIL("C.Main", @" { // Code size 163 (0xa3) .maxstack 7 .locals init (C V_0) //a IL_0000: newobj ""C..ctor()"" IL_0005: dup IL_0006: ldfld ""int[,] C.a"" IL_000b: ldc.i4.0 IL_000c: ldc.i4.0 IL_000d: ldc.i4.1 IL_000e: call ""int[*,*].Set"" IL_0013: dup IL_0014: ldfld ""int[,] C.a"" IL_0019: ldc.i4.0 IL_001a: ldc.i4.1 IL_001b: ldc.i4.2 IL_001c: call ""int[*,*].Set"" IL_0021: dup IL_0022: ldfld ""int[,] C.a"" IL_0027: ldc.i4.1 IL_0028: ldc.i4.0 IL_0029: ldc.i4.3 IL_002a: call ""int[*,*].Set"" IL_002f: dup IL_0030: ldfld ""int[,] C.a"" IL_0035: ldc.i4.1 IL_0036: ldc.i4.1 IL_0037: ldc.i4.4 IL_0038: call ""int[*,*].Set"" IL_003d: stloc.0 IL_003e: ldstr ""{0} {1} {2} {3}"" IL_0043: ldc.i4.4 IL_0044: newarr ""object"" IL_0049: dup IL_004a: ldc.i4.0 IL_004b: ldloc.0 IL_004c: ldfld ""int[,] C.a"" IL_0051: ldc.i4.0 IL_0052: ldc.i4.0 IL_0053: call ""int[*,*].Get"" IL_0058: box ""int"" IL_005d: stelem.ref IL_005e: dup IL_005f: ldc.i4.1 IL_0060: ldloc.0 IL_0061: ldfld ""int[,] C.a"" IL_0066: ldc.i4.0 IL_0067: ldc.i4.1 IL_0068: call ""int[*,*].Get"" IL_006d: box ""int"" IL_0072: stelem.ref IL_0073: dup IL_0074: ldc.i4.2 IL_0075: ldloc.0 IL_0076: ldfld ""int[,] C.a"" IL_007b: ldc.i4.1 IL_007c: ldc.i4.0 IL_007d: call ""int[*,*].Get"" IL_0082: box ""int"" IL_0087: stelem.ref IL_0088: dup IL_0089: ldc.i4.3 IL_008a: ldloc.0 IL_008b: ldfld ""int[,] C.a"" IL_0090: ldc.i4.1 IL_0091: ldc.i4.1 IL_0092: call ""int[*,*].Get"" IL_0097: box ""int"" IL_009c: stelem.ref IL_009d: call ""void System.Console.Write(string, params object[])"" IL_00a2: ret }"); } [Fact, WorkItem(1073330, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1073330")] public void NestedIndexerInitializerJaggedArrayNestedInitializer() { var source = @" class C { int[][] a = new int[1][] { new int[2] }; static void Main() { var a = new C { a = { [0] = { [0] = 1, [1] = 2 } } }; System.Console.Write(""{0} {1}"", a.a[0][0], a.a[0][1]); } } "; CompileAndVerify(source, expectedOutput: "1 2").VerifyIL("C.Main", @" { // Code size 69 (0x45) .maxstack 4 .locals init (C V_0) //a IL_0000: newobj ""C..ctor()"" IL_0005: dup IL_0006: ldfld ""int[][] C.a"" IL_000b: ldc.i4.0 IL_000c: ldelem.ref IL_000d: ldc.i4.0 IL_000e: ldc.i4.1 IL_000f: stelem.i4 IL_0010: dup IL_0011: ldfld ""int[][] C.a"" IL_0016: ldc.i4.0 IL_0017: ldelem.ref IL_0018: ldc.i4.1 IL_0019: ldc.i4.2 IL_001a: stelem.i4 IL_001b: stloc.0 IL_001c: ldstr ""{0} {1}"" IL_0021: ldloc.0 IL_0022: ldfld ""int[][] C.a"" IL_0027: ldc.i4.0 IL_0028: ldelem.ref IL_0029: ldc.i4.0 IL_002a: ldelem.i4 IL_002b: box ""int"" IL_0030: ldloc.0 IL_0031: ldfld ""int[][] C.a"" IL_0036: ldc.i4.0 IL_0037: ldelem.ref IL_0038: ldc.i4.1 IL_0039: ldelem.i4 IL_003a: box ""int"" IL_003f: call ""void System.Console.Write(string, object, object)"" IL_0044: ret }"); } [Fact, WorkItem(1073330, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1073330")] public void NestedIndexerInitializerArrayNestedObjectInitializer() { var source = @" class C { C[] a; int b; C() { } C(bool unused) { this.a = new C[2] { new C(), new C() }; } static void Main() { var a = new C(true) { a = { [0] = { b = 1 }, [1] = { b = 2 } } }; System.Console.Write(""{0} {1}"", a.a[0].b, a.a[1].b); } } "; CompileAndVerify(source, expectedOutput: "1 2").VerifyIL("C.Main", @" { // Code size 82 (0x52) .maxstack 4 .locals init (C V_0) //a IL_0000: ldc.i4.1 IL_0001: newobj ""C..ctor(bool)"" IL_0006: dup IL_0007: ldfld ""C[] C.a"" IL_000c: ldc.i4.0 IL_000d: ldelem.ref IL_000e: ldc.i4.1 IL_000f: stfld ""int C.b"" IL_0014: dup IL_0015: ldfld ""C[] C.a"" IL_001a: ldc.i4.1 IL_001b: ldelem.ref IL_001c: ldc.i4.2 IL_001d: stfld ""int C.b"" IL_0022: stloc.0 IL_0023: ldstr ""{0} {1}"" IL_0028: ldloc.0 IL_0029: ldfld ""C[] C.a"" IL_002e: ldc.i4.0 IL_002f: ldelem.ref IL_0030: ldfld ""int C.b"" IL_0035: box ""int"" IL_003a: ldloc.0 IL_003b: ldfld ""C[] C.a"" IL_0040: ldc.i4.1 IL_0041: ldelem.ref IL_0042: ldfld ""int C.b"" IL_0047: box ""int"" IL_004c: call ""void System.Console.Write(string, object, object)"" IL_0051: ret }"); } #endregion #region "Collection Initializer Tests" [Fact] public void CollectionInitializerTest_GenericList() { var source = @" using System; using System.Collections.Generic; using System.Collections; class Test { public static int Main() { List<int> list = new List<int>() { 1, 2, 3, 4, 5 }; DisplayCollection(list); return 0; } public static void DisplayCollection<T>(IEnumerable<T> collection) { foreach (var i in collection) { Console.WriteLine(i); } } } "; string expectedOutput = @"1 2 3 4 5"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 47 (0x2f) .maxstack 3 IL_0000: newobj ""System.Collections.Generic.List<int>..ctor()"" IL_0005: dup IL_0006: ldc.i4.1 IL_0007: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_000c: dup IL_000d: ldc.i4.2 IL_000e: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0013: dup IL_0014: ldc.i4.3 IL_0015: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_001a: dup IL_001b: ldc.i4.4 IL_001c: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0021: dup IL_0022: ldc.i4.5 IL_0023: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0028: call ""void Test.DisplayCollection<int>(System.Collections.Generic.IEnumerable<int>)"" IL_002d: ldc.i4.0 IL_002e: ret }"); } [Fact] public void CollectionInitializerTest_GenericList_WithComplexElementInitializer() { var source = @" using System; using System.Collections.Generic; using System.Collections; class Test { public static int Main() { List<long> list = new List<long>() { 1, 2, { 4L }, { 9 }, 3L }; DisplayCollection(list); return 0; } public static void DisplayCollection<T>(IEnumerable<T> collection) { foreach (var i in collection) { Console.WriteLine(i); } } } "; string expectedOutput = @"1 2 4 9 3"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 53 (0x35) .maxstack 3 IL_0000: newobj ""System.Collections.Generic.List<long>..ctor()"" IL_0005: dup IL_0006: ldc.i4.1 IL_0007: conv.i8 IL_0008: callvirt ""void System.Collections.Generic.List<long>.Add(long)"" IL_000d: dup IL_000e: ldc.i4.2 IL_000f: conv.i8 IL_0010: callvirt ""void System.Collections.Generic.List<long>.Add(long)"" IL_0015: dup IL_0016: ldc.i4.4 IL_0017: conv.i8 IL_0018: callvirt ""void System.Collections.Generic.List<long>.Add(long)"" IL_001d: dup IL_001e: ldc.i4.s 9 IL_0020: conv.i8 IL_0021: callvirt ""void System.Collections.Generic.List<long>.Add(long)"" IL_0026: dup IL_0027: ldc.i4.3 IL_0028: conv.i8 IL_0029: callvirt ""void System.Collections.Generic.List<long>.Add(long)"" IL_002e: call ""void Test.DisplayCollection<long>(System.Collections.Generic.IEnumerable<long>)"" IL_0033: ldc.i4.0 IL_0034: ret }"); } [Fact] public void CollectionInitializerTest_TypeParameter() { var source = @" using System; using System.Collections; using System.Collections.Generic; class A:IEnumerable { public static List<int> list = new List<int>(); public void Add(int i) { list.Add(i); } public IEnumerator GetEnumerator() { for (int i = 0; i < list.Count; i++) yield return list[i]; } } class C<T> where T: A, new() { public void M() { T t = new T {1, 2, 3, 4, 5}; foreach (var x in t) { Console.WriteLine(x); } } } class Test { static void Main() { C<A> testC = new C<A>(); testC.M(); } } "; string expectedOutput = @"1 2 3 4 5"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("C<T>.M", @" { // Code size 117 (0x75) .maxstack 3 .locals init (System.Collections.IEnumerator V_0, System.IDisposable V_1) IL_0000: call ""T System.Activator.CreateInstance<T>()"" IL_0005: dup IL_0006: box ""T"" IL_000b: ldc.i4.1 IL_000c: callvirt ""void A.Add(int)"" IL_0011: dup IL_0012: box ""T"" IL_0017: ldc.i4.2 IL_0018: callvirt ""void A.Add(int)"" IL_001d: dup IL_001e: box ""T"" IL_0023: ldc.i4.3 IL_0024: callvirt ""void A.Add(int)"" IL_0029: dup IL_002a: box ""T"" IL_002f: ldc.i4.4 IL_0030: callvirt ""void A.Add(int)"" IL_0035: dup IL_0036: box ""T"" IL_003b: ldc.i4.5 IL_003c: callvirt ""void A.Add(int)"" IL_0041: box ""T"" IL_0046: callvirt ""System.Collections.IEnumerator A.GetEnumerator()"" IL_004b: stloc.0 .try { IL_004c: br.s IL_0059 IL_004e: ldloc.0 IL_004f: callvirt ""object System.Collections.IEnumerator.Current.get"" IL_0054: call ""void System.Console.WriteLine(object)"" IL_0059: ldloc.0 IL_005a: callvirt ""bool System.Collections.IEnumerator.MoveNext()"" IL_005f: brtrue.s IL_004e IL_0061: leave.s IL_0074 } finally { IL_0063: ldloc.0 IL_0064: isinst ""System.IDisposable"" IL_0069: stloc.1 IL_006a: ldloc.1 IL_006b: brfalse.s IL_0073 IL_006d: ldloc.1 IL_006e: callvirt ""void System.IDisposable.Dispose()"" IL_0073: endfinally } IL_0074: ret }"); } [Fact] public void CollectionInitializerTest_InitializerTypeImplementsIEnumerable_ClassType() { var source = @" using System; using System.Collections.Generic; using System.Collections; class Test { public static int Main() { B coll = new B { 1, 2, { 4L }, { 9 }, 3L }; DisplayCollection(coll.GetEnumerator()); return 0; } public static void DisplayCollection(IEnumerator collection) { while (collection.MoveNext()) { Console.WriteLine(collection.Current); } } } public class B : IEnumerable { List<object> list = new List<object>(); public void Add(long i) { list.Add(i); } public IEnumerator GetEnumerator() { for (int i = 0; i < list.Count; i++) yield return list[i]; } } "; string expectedOutput = @"1 2 4 9 3"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 58 (0x3a) .maxstack 3 IL_0000: newobj ""B..ctor()"" IL_0005: dup IL_0006: ldc.i4.1 IL_0007: conv.i8 IL_0008: callvirt ""void B.Add(long)"" IL_000d: dup IL_000e: ldc.i4.2 IL_000f: conv.i8 IL_0010: callvirt ""void B.Add(long)"" IL_0015: dup IL_0016: ldc.i4.4 IL_0017: conv.i8 IL_0018: callvirt ""void B.Add(long)"" IL_001d: dup IL_001e: ldc.i4.s 9 IL_0020: conv.i8 IL_0021: callvirt ""void B.Add(long)"" IL_0026: dup IL_0027: ldc.i4.3 IL_0028: conv.i8 IL_0029: callvirt ""void B.Add(long)"" IL_002e: callvirt ""System.Collections.IEnumerator B.GetEnumerator()"" IL_0033: call ""void Test.DisplayCollection(System.Collections.IEnumerator)"" IL_0038: ldc.i4.0 IL_0039: ret }"); } [Fact] public void CollectionInitializerTest_InitializerTypeImplementsIEnumerable_StructType() { var source = @" using System; using System.Collections.Generic; using System.Collections; class Test { public static int Main() { B coll = new B(1) { 2, { 4L }, { 9 }, 3L }; DisplayCollection(coll.GetEnumerator()); return 0; } public static void DisplayCollection(IEnumerator collection) { while (collection.MoveNext()) { Console.WriteLine(collection.Current); } } } public struct B : IEnumerable { List<object> list; public B(long i) { list = new List<object>(); Add(i); } public void Add(long i) { list.Add(i); } public IEnumerator GetEnumerator() { for (int i = 0; i < list.Count; i++) yield return list[i]; } } "; string expectedOutput = @"1 2 4 9 3"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 62 (0x3e) .maxstack 2 .locals init (B V_0, //coll B V_1) IL_0000: ldloca.s V_1 IL_0002: ldc.i4.1 IL_0003: conv.i8 IL_0004: call ""B..ctor(long)"" IL_0009: ldloca.s V_1 IL_000b: ldc.i4.2 IL_000c: conv.i8 IL_000d: call ""void B.Add(long)"" IL_0012: ldloca.s V_1 IL_0014: ldc.i4.4 IL_0015: conv.i8 IL_0016: call ""void B.Add(long)"" IL_001b: ldloca.s V_1 IL_001d: ldc.i4.s 9 IL_001f: conv.i8 IL_0020: call ""void B.Add(long)"" IL_0025: ldloca.s V_1 IL_0027: ldc.i4.3 IL_0028: conv.i8 IL_0029: call ""void B.Add(long)"" IL_002e: ldloc.1 IL_002f: stloc.0 IL_0030: ldloca.s V_0 IL_0032: call ""System.Collections.IEnumerator B.GetEnumerator()"" IL_0037: call ""void Test.DisplayCollection(System.Collections.IEnumerator)"" IL_003c: ldc.i4.0 IL_003d: ret }"); } [Fact] public void CollectionInitializerTest_InitializerTypeImplementsIEnumerable_MultipleAddOverloads() { var source = @" using System; using System.Collections.Generic; using System.Collections; class Test { public static int Main() { B coll = new B { 1, 2, { 4L }, { 9 }, 3L }; DisplayCollection(coll.GetEnumerator()); return 0; } public static void DisplayCollection(IEnumerator collection) { while (collection.MoveNext()) { Console.WriteLine(collection.Current); } } } public class B : IEnumerable { List<object> list = new List<object>(); public B() { } public B(int i) { } public void Add(int i) { list.Add(i); } public void Add(long i) { list.Add(i); } public IEnumerator GetEnumerator() { for (int i = 0; i < list.Count; i++) yield return list[i]; } } "; string expectedOutput = @"1 2 4 9 3"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 55 (0x37) .maxstack 3 IL_0000: newobj ""B..ctor()"" IL_0005: dup IL_0006: ldc.i4.1 IL_0007: callvirt ""void B.Add(int)"" IL_000c: dup IL_000d: ldc.i4.2 IL_000e: callvirt ""void B.Add(int)"" IL_0013: dup IL_0014: ldc.i4.4 IL_0015: conv.i8 IL_0016: callvirt ""void B.Add(long)"" IL_001b: dup IL_001c: ldc.i4.s 9 IL_001e: callvirt ""void B.Add(int)"" IL_0023: dup IL_0024: ldc.i4.3 IL_0025: conv.i8 IL_0026: callvirt ""void B.Add(long)"" IL_002b: callvirt ""System.Collections.IEnumerator B.GetEnumerator()"" IL_0030: call ""void Test.DisplayCollection(System.Collections.IEnumerator)"" IL_0035: ldc.i4.0 IL_0036: ret }"); } [Fact] public void CollectionInitializerTest_InitializerTypeImplementsIEnumerable_AddOverload_OptionalArgument() { var source = @" using System; using System.Collections.Generic; using System.Collections; class Test { public static int Main() { D coll = new D { 1, { 2 }, { 3, (float?)4.4 } }; DisplayCollection(coll.GetEnumerator()); return 0; } public static void DisplayCollection(IEnumerator collection) { while (collection.MoveNext()) { if (collection.Current.GetType() == typeof(float)) Console.WriteLine(((float)collection.Current).ToString(System.Globalization.CultureInfo.InvariantCulture)); else Console.WriteLine(collection.Current); } } } public class D : IEnumerable { List<object> list = new List<object>(); public D() { } public void Add(int i, float? j = null) { list.Add(i); if (j.HasValue) { list.Add(j); } } public IEnumerator GetEnumerator() { for (int i = 0; i < list.Count; i++) yield return list[i]; } } "; string expectedOutput = @"1 2 3 4.4"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 66 (0x42) .maxstack 4 .locals init (float? V_0) IL_0000: newobj ""D..ctor()"" IL_0005: dup IL_0006: ldc.i4.1 IL_0007: ldloca.s V_0 IL_0009: initobj ""float?"" IL_000f: ldloc.0 IL_0010: callvirt ""void D.Add(int, float?)"" IL_0015: dup IL_0016: ldc.i4.2 IL_0017: ldloca.s V_0 IL_0019: initobj ""float?"" IL_001f: ldloc.0 IL_0020: callvirt ""void D.Add(int, float?)"" IL_0025: dup IL_0026: ldc.i4.3 IL_0027: ldc.r4 4.4 IL_002c: newobj ""float?..ctor(float)"" IL_0031: callvirt ""void D.Add(int, float?)"" IL_0036: callvirt ""System.Collections.IEnumerator D.GetEnumerator()"" IL_003b: call ""void Test.DisplayCollection(System.Collections.IEnumerator)"" IL_0040: ldc.i4.0 IL_0041: ret }"); } [Fact] public void CollectionInitializerTest_InitializerTypeImplementsIEnumerable_AddOverload_ParamsArrayArgument() { var source = @" using System; using System.Collections.Generic; using System.Collections; class Test { public static int Main() { var implicitTypedArr = new[] { 7.7, 8.8 }; D coll = new D { 1, { 2 }, { 3, 4.4 }, new double[] { 5, 6 }, implicitTypedArr, null }; DisplayCollection(coll.GetEnumerator()); return 0; } public static void DisplayCollection(IEnumerator collection) { while (collection.MoveNext()) { if (collection.Current.GetType() == typeof(double)) Console.WriteLine(((double)collection.Current).ToString(System.Globalization.CultureInfo.InvariantCulture)); else Console.WriteLine(collection.Current); } } } public class D : IEnumerable { List<object> list = new List<object>(); public D() { } public void Add(params double[] i) { if (i != null) { foreach (var x in i) { list.Add(x); } } } public IEnumerator GetEnumerator() { for (int i = 0; i < list.Count; i++) yield return list[i]; } } "; string expectedOutput = @"1 2 3 4.4 5 6 7.7 8.8"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 184 (0xb8) .maxstack 5 .locals init (double[] V_0, //implicitTypedArr D V_1) IL_0000: ldc.i4.2 IL_0001: newarr ""double"" IL_0006: dup IL_0007: ldc.i4.0 IL_0008: ldc.r8 7.7 IL_0011: stelem.r8 IL_0012: dup IL_0013: ldc.i4.1 IL_0014: ldc.r8 8.8 IL_001d: stelem.r8 IL_001e: stloc.0 IL_001f: newobj ""D..ctor()"" IL_0024: stloc.1 IL_0025: ldloc.1 IL_0026: ldc.i4.1 IL_0027: newarr ""double"" IL_002c: dup IL_002d: ldc.i4.0 IL_002e: ldc.r8 1 IL_0037: stelem.r8 IL_0038: callvirt ""void D.Add(params double[])"" IL_003d: ldloc.1 IL_003e: ldc.i4.1 IL_003f: newarr ""double"" IL_0044: dup IL_0045: ldc.i4.0 IL_0046: ldc.r8 2 IL_004f: stelem.r8 IL_0050: callvirt ""void D.Add(params double[])"" IL_0055: ldloc.1 IL_0056: ldc.i4.2 IL_0057: newarr ""double"" IL_005c: dup IL_005d: ldc.i4.0 IL_005e: ldc.r8 3 IL_0067: stelem.r8 IL_0068: dup IL_0069: ldc.i4.1 IL_006a: ldc.r8 4.4 IL_0073: stelem.r8 IL_0074: callvirt ""void D.Add(params double[])"" IL_0079: ldloc.1 IL_007a: ldc.i4.2 IL_007b: newarr ""double"" IL_0080: dup IL_0081: ldc.i4.0 IL_0082: ldc.r8 5 IL_008b: stelem.r8 IL_008c: dup IL_008d: ldc.i4.1 IL_008e: ldc.r8 6 IL_0097: stelem.r8 IL_0098: callvirt ""void D.Add(params double[])"" IL_009d: ldloc.1 IL_009e: ldloc.0 IL_009f: callvirt ""void D.Add(params double[])"" IL_00a4: ldloc.1 IL_00a5: ldnull IL_00a6: callvirt ""void D.Add(params double[])"" IL_00ab: ldloc.1 IL_00ac: callvirt ""System.Collections.IEnumerator D.GetEnumerator()"" IL_00b1: call ""void Test.DisplayCollection(System.Collections.IEnumerator)"" IL_00b6: ldc.i4.0 IL_00b7: ret }"); } [Fact] public void CollectionInitializerTest_NestedCollectionInitializerExpression() { var source = @" using System; using System.Collections.Generic; using System.Collections; class Test { public static int Main() { var listOfList = new List<List<int>>() { new List<int> { 1, 2, 3, 4, 5 }, new List<int> { 6, 7, 8, 9, 10 } }; DisplayCollectionOfCollection(listOfList); return 0; } public static void DisplayCollectionOfCollection(IEnumerable<List<int>> collectionOfCollection) { foreach (var collection in collectionOfCollection) { foreach (var i in collection) { Console.WriteLine(i); } } } } "; string expectedOutput = @"1 2 3 4 5 6 7 8 9 10"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 106 (0x6a) .maxstack 5 IL_0000: newobj ""System.Collections.Generic.List<System.Collections.Generic.List<int>>..ctor()"" IL_0005: dup IL_0006: newobj ""System.Collections.Generic.List<int>..ctor()"" IL_000b: dup IL_000c: ldc.i4.1 IL_000d: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0012: dup IL_0013: ldc.i4.2 IL_0014: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0019: dup IL_001a: ldc.i4.3 IL_001b: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0020: dup IL_0021: ldc.i4.4 IL_0022: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0027: dup IL_0028: ldc.i4.5 IL_0029: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_002e: callvirt ""void System.Collections.Generic.List<System.Collections.Generic.List<int>>.Add(System.Collections.Generic.List<int>)"" IL_0033: dup IL_0034: newobj ""System.Collections.Generic.List<int>..ctor()"" IL_0039: dup IL_003a: ldc.i4.6 IL_003b: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0040: dup IL_0041: ldc.i4.7 IL_0042: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0047: dup IL_0048: ldc.i4.8 IL_0049: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_004e: dup IL_004f: ldc.i4.s 9 IL_0051: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0056: dup IL_0057: ldc.i4.s 10 IL_0059: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_005e: callvirt ""void System.Collections.Generic.List<System.Collections.Generic.List<int>>.Add(System.Collections.Generic.List<int>)"" IL_0063: call ""void Test.DisplayCollectionOfCollection(System.Collections.Generic.IEnumerable<System.Collections.Generic.List<int>>)"" IL_0068: ldc.i4.0 IL_0069: ret }"); } [Fact] public void CollectionInitializerTest_NestedObjectAndCollectionInitializer() { var source = @" using System; using System.Collections.Generic; using System.Collections; class Test { public static int Main() { var coll = new List<B> { new B(0) { list = new List<int>() { 1, 2, 3 } }, new B(1) { list = { 2, 3 } } }; DisplayCollection(coll); return 0; } public static void DisplayCollection(IEnumerable<B> collection) { foreach (var i in collection) { i.Display(); } } } public class B { public List<int> list = new List<int>(); public B() { } public B(int i) { list.Add(i); } public void Display() { foreach (var i in list) { Console.WriteLine(i); } } } "; string expectedOutput = @"1 2 3 1 2 3"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 92 (0x5c) .maxstack 7 IL_0000: newobj ""System.Collections.Generic.List<B>..ctor()"" IL_0005: dup IL_0006: ldc.i4.0 IL_0007: newobj ""B..ctor(int)"" IL_000c: dup IL_000d: newobj ""System.Collections.Generic.List<int>..ctor()"" IL_0012: dup IL_0013: ldc.i4.1 IL_0014: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0019: dup IL_001a: ldc.i4.2 IL_001b: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0020: dup IL_0021: ldc.i4.3 IL_0022: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0027: stfld ""System.Collections.Generic.List<int> B.list"" IL_002c: callvirt ""void System.Collections.Generic.List<B>.Add(B)"" IL_0031: dup IL_0032: ldc.i4.1 IL_0033: newobj ""B..ctor(int)"" IL_0038: dup IL_0039: ldfld ""System.Collections.Generic.List<int> B.list"" IL_003e: ldc.i4.2 IL_003f: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0044: dup IL_0045: ldfld ""System.Collections.Generic.List<int> B.list"" IL_004a: ldc.i4.3 IL_004b: callvirt ""void System.Collections.Generic.List<int>.Add(int)"" IL_0050: callvirt ""void System.Collections.Generic.List<B>.Add(B)"" IL_0055: call ""void Test.DisplayCollection(System.Collections.Generic.IEnumerable<B>)"" IL_005a: ldc.i4.0 IL_005b: ret }"); } [Fact] public void CollectionInitializerTest_CtorAddsToCollection() { var source = @" using System; using System.Collections.Generic; using System.Collections; class Test { public static int Main() { B coll = new B(1) { 2 }; DisplayCollection(coll.GetEnumerator()); return 0; } public static void DisplayCollection(IEnumerator collection) { while (collection.MoveNext()) { Console.WriteLine(collection.Current); } } } public class B : IEnumerable { List<object> list = new List<object>(); public B() { } public B(int i) { list.Add(i); } public void Add(long i) { list.Add(i); } public IEnumerator GetEnumerator() { for (int i = 0; i < list.Count; i++) yield return list[i]; } } "; string expectedOutput = @"1 2"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 26 (0x1a) .maxstack 3 IL_0000: ldc.i4.1 IL_0001: newobj ""B..ctor(int)"" IL_0006: dup IL_0007: ldc.i4.2 IL_0008: conv.i8 IL_0009: callvirt ""void B.Add(long)"" IL_000e: callvirt ""System.Collections.IEnumerator B.GetEnumerator()"" IL_0013: call ""void Test.DisplayCollection(System.Collections.IEnumerator)"" IL_0018: ldc.i4.0 IL_0019: ret }"); } [Fact] public void CollectionInitializerTest_NestedObjectAndCollectionInitializer_02() { // -------------------------------------------------------------------------------------------- // SPEC: 7.6.10.3 Collection initializers // -------------------------------------------------------------------------------------------- // // SPEC: The following class represents a contact with a name and a list of phone numbers: // // SPEC: public class Contact // SPEC: { // SPEC: string name; // SPEC: List<string> phoneNumbers = new List<string>(); // SPEC: public string Name { get { return name; } set { name = value; } } // SPEC: public List<string> PhoneNumbers { get { return phoneNumbers; } } // SPEC: } // // SPEC: A List<Contact> can be created and initialized as follows: // // SPEC: var contacts = new List<Contact> { // SPEC: new Contact { // SPEC: Name = "Chris Smith", // SPEC: PhoneNumbers = { "206-555-0101", "425-882-8080" } // SPEC: }, // SPEC: new Contact { // SPEC: Name = "Bob Harris", // SPEC: PhoneNumbers = { "650-555-0199" } // SPEC: } // SPEC: }; // // SPEC: which has the same effect as // // SPEC: var __clist = new List<Contact>(); // SPEC: Contact __c1 = new Contact(); // SPEC: __c1.Name = "Chris Smith"; // SPEC: __c1.PhoneNumbers.Add("206-555-0101"); // SPEC: __c1.PhoneNumbers.Add("425-882-8080"); // SPEC: __clist.Add(__c1); // SPEC: Contact __c2 = new Contact(); // SPEC: __c2.Name = "Bob Harris"; // SPEC: __c2.PhoneNumbers.Add("650-555-0199"); // SPEC: __clist.Add(__c2); // SPEC: var contacts = __clist; // // SPEC: where __clist, __c1 and __c2 are temporary variables that are otherwise invisible and inaccessible. var source = @" using System; using System.Collections.Generic; using System.Collections; public class Contact { string name; List<string> phoneNumbers = new List<string>(); public string Name { get { return name; } set { name = value; } } public List<string> PhoneNumbers { get { return phoneNumbers; } } public void DisplayContact() { Console.WriteLine(""Name:"" + name); Console.WriteLine(""PH:""); foreach (var ph in phoneNumbers) { Console.WriteLine(ph); } } } class Test { public static void Main() { var contacts = new List<Contact> { new Contact { Name = ""Chris Smith"", PhoneNumbers = { ""206-555-0101"", ""425-882-8080"" } }, new Contact { Name = ""Bob Harris"", PhoneNumbers = { ""650-555-0199"" } } }; DisplayContacts(contacts); } public static void DisplayContacts(IEnumerable<Contact> contacts) { foreach (var contact in contacts) { contact.DisplayContact(); } } } "; string expectedOutput = @"Name:Chris Smith PH: 206-555-0101 425-882-8080 Name:Bob Harris PH: 650-555-0199"; var compVerifier = CompileAndVerify(source, expectedOutput: expectedOutput); compVerifier.VerifyIL("Test.Main", @" { // Code size 103 (0x67) .maxstack 5 IL_0000: newobj ""System.Collections.Generic.List<Contact>..ctor()"" IL_0005: dup IL_0006: newobj ""Contact..ctor()"" IL_000b: dup IL_000c: ldstr ""Chris Smith"" IL_0011: callvirt ""void Contact.Name.set"" IL_0016: dup IL_0017: callvirt ""System.Collections.Generic.List<string> Contact.PhoneNumbers.get"" IL_001c: ldstr ""206-555-0101"" IL_0021: callvirt ""void System.Collections.Generic.List<string>.Add(string)"" IL_0026: dup IL_0027: callvirt ""System.Collections.Generic.List<string> Contact.PhoneNumbers.get"" IL_002c: ldstr ""425-882-8080"" IL_0031: callvirt ""void System.Collections.Generic.List<string>.Add(string)"" IL_0036: callvirt ""void System.Collections.Generic.List<Contact>.Add(Contact)"" IL_003b: dup IL_003c: newobj ""Contact..ctor()"" IL_0041: dup IL_0042: ldstr ""Bob Harris"" IL_0047: callvirt ""void Contact.Name.set"" IL_004c: dup IL_004d: callvirt ""System.Collections.Generic.List<string> Contact.PhoneNumbers.get"" IL_0052: ldstr ""650-555-0199"" IL_0057: callvirt ""void System.Collections.Generic.List<string>.Add(string)"" IL_005c: callvirt ""void System.Collections.Generic.List<Contact>.Add(Contact)"" IL_0061: call ""void Test.DisplayContacts(System.Collections.Generic.IEnumerable<Contact>)"" IL_0066: ret }"); } [Fact] public void PartialAddMethods() { var source = @" using System; using System.Collections; partial class C : IEnumerable { public IEnumerator GetEnumerator() { return null; } partial void Add(int i); partial void Add(char c); partial void Add(char c) { } static void Main() { Console.WriteLine(new C { 1, 2, 3 }); // all removed Console.WriteLine(new C { 1, 'b', 3 }); // some removed Console.WriteLine(new C { 'a', 'b', 'c' }); // none removed } }"; CompileAndVerify(source).VerifyIL("C.Main", @" { // Code size 63 (0x3f) .maxstack 3 IL_0000: newobj ""C..ctor()"" IL_0005: call ""void System.Console.WriteLine(object)"" IL_000a: newobj ""C..ctor()"" IL_000f: dup IL_0010: ldc.i4.s 98 IL_0012: callvirt ""void C.Add(char)"" IL_0017: call ""void System.Console.WriteLine(object)"" IL_001c: newobj ""C..ctor()"" IL_0021: dup IL_0022: ldc.i4.s 97 IL_0024: callvirt ""void C.Add(char)"" IL_0029: dup IL_002a: ldc.i4.s 98 IL_002c: callvirt ""void C.Add(char)"" IL_0031: dup IL_0032: ldc.i4.s 99 IL_0034: callvirt ""void C.Add(char)"" IL_0039: call ""void System.Console.WriteLine(object)"" IL_003e: ret } "); } [Fact, WorkItem(1089276, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1089276")] public void PointerIndexing_01() { var source = @" unsafe class C { int* X; static void Main() { var array = new[] { 0 }; fixed (int* p = array) { new C(p) { X = {[0] = 1 } }; } System.Console.WriteLine(array[0]); } C(int* x) { X = x; } }"; CompileAndVerify(source, options: TestOptions.DebugExe.WithAllowUnsafe(true), expectedOutput: "1", verify: Verification.Fails); } [Fact, WorkItem(1089276, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1089276")] public void PointerIndexing_02() { var source = @" unsafe class C { int** X; static void Main() { var array = new[] { 0, 0 }; fixed (int* p = array) { var array2 = new[] { p }; fixed (int** pp = array2 ) { M(pp); } } System.Console.WriteLine(array[0]); System.Console.WriteLine(array[1]); } static C M(int** pp) { return new C(pp) { X = {[Index] = {[0] = 2, [1] = 3} } }; } static int Index { get { System.Console.WriteLine(""get_Index""); return 0; } } C(int** x) { X = x; } }"; var verifier = CompileAndVerify(source, options: TestOptions.DebugExe.WithAllowUnsafe(true), verify: Verification.Fails, expectedOutput: @"get_Index 2 3"); var comp = verifier.Compilation; var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); var node = tree.GetRoot().DescendantNodes().OfType<Syntax.ObjectCreationExpressionSyntax>().Single(); Assert.Equal("new C(pp) { X = {[Index] = {[0] = 2, [1] = 3} } }", node.ToString()); var (graph, symbol) = ControlFlowGraphVerifier.GetControlFlowGraph(node.Parent.Parent, model); ControlFlowGraphVerifier.VerifyGraph(comp, """ Block[B0] - Entry Statements (0) Next (Regular) Block[B1] Entering: {R1} .locals {R1} { CaptureIds: [0] Block[B1] - Block Predecessors: [B0] Statements (3) IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'new C(pp) { ... 1] = 3} } }') Value: IObjectCreationOperation (Constructor: C..ctor(System.Int32** x)) (OperationKind.ObjectCreation, Type: C) (Syntax: 'new C(pp) { ... 1] = 3} } }') Arguments(1): IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: x) (OperationKind.Argument, Type: null) (Syntax: 'pp') IParameterReferenceOperation: pp (OperationKind.ParameterReference, Type: System.Int32**) (Syntax: 'pp') InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Initializer: null ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: '[0] = 2') Left: IOperation: (OperationKind.None, Type: System.Int32) (Syntax: '[0]') Children(2): IOperation: (OperationKind.None, Type: System.Int32*) (Syntax: '[Index]') Children(2): IFieldReferenceOperation: System.Int32** C.X (OperationKind.FieldReference, Type: System.Int32**) (Syntax: 'X') Instance Receiver: IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'new C(pp) { ... 1] = 3} } }') IPropertyReferenceOperation: System.Int32 C.Index { get; } (Static) (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'Index') Instance Receiver: null ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0') Right: ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: '[1] = 3') Left: IOperation: (OperationKind.None, Type: System.Int32) (Syntax: '[1]') Children(2): IOperation: (OperationKind.None, Type: System.Int32*) (Syntax: '[Index]') Children(2): IFieldReferenceOperation: System.Int32** C.X (OperationKind.FieldReference, Type: System.Int32**) (Syntax: 'X') Instance Receiver: IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'new C(pp) { ... 1] = 3} } }') IPropertyReferenceOperation: System.Int32 C.Index { get; } (Static) (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'Index') Instance Receiver: null ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') Right: ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 3) (Syntax: '3') Next (Return) Block[B2] IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'new C(pp) { ... 1] = 3} } }') Leaving: {R1} } Block[B2] - Exit Predecessors: [B1] Statements (0) """, graph, symbol); } [Fact] [WorkItem(38726, "https://github.com/dotnet/roslyn/issues/38726")] public void CollectionInitializerBoxingConversion_01() { var source = @"using System; using System.Collections; interface IAppend { void Append(object o); } struct S1 { internal S2 S2; } struct S2 : IEnumerable, IAppend { IEnumerator IEnumerable.GetEnumerator() => null; void IAppend.Append(object o) { } } static class Program { static void Add(this IAppend x, object y) { x.Append(y); Console.Write(y); } static void Main() { _ = new S2() { 1, 2 }; _ = new S1() { S2 = { 3, 4 } }; } }"; var comp = CSharpTestBase.CreateCompilation(source, options: TestOptions.ReleaseExe); CompileAndVerify(comp, expectedOutput: "1234"); } [Fact] [WorkItem(38726, "https://github.com/dotnet/roslyn/issues/38726")] public void CollectionInitializerBoxingConversion_02() { var source = @"using System; using System.Collections; interface IAppend { void Append(object o); } struct S : IEnumerable, IAppend { IEnumerator IEnumerable.GetEnumerator() => null; void IAppend.Append(object o) { } } static class Program { static void Add(this IAppend x, object y) { x.Append(y); Console.Write(y); } static T F<T>() where T : IEnumerable, IAppend, new() { return new T() { 1, 2 }; } static void Main() { _ = F<S>(); } }"; var comp = CSharpTestBase.CreateCompilation(source, options: TestOptions.ReleaseExe); CompileAndVerify(comp, expectedOutput: "12"); } #endregion } }