/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExplicitImplementationTests.cs
1 088 строк
42 KB
Jared Parsons
generated move
28 сен 2020, 19:36
28 сен 2020, 19:36
1cca63b
Код
Авторство
О чём код?
// 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; using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.CSharp.UnitTests.Emit; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen { public class CodeGenExplicitImplementationTests : CSharpTestBase { [Fact] public void TestExplicitInterfaceMethodImplementationSource() { var source = @" interface I1 { void Method(); } interface I2 { void Method(); } class C : I1, I2 { public void Method() { System.Console.WriteLine(""C.Method""); } void I1.Method() { System.Console.WriteLine(""I1.Method""); } void I2.Method() { System.Console.WriteLine(""I2.Method""); } static void Main() { C c = new C(); c.Method(); ((I1)c).Method(); ((I2)c).Method(); } } "; CompileAndVerify(source, expectedOutput: @" C.Method I1.Method I2.Method "); } [Fact] public void TestExplicitInterfacePropertyImplementationSource() { var text1 = @" public interface I1 { string Property { get; } } public interface I2 { string Property { get; } } public class C : I1, I2 { public string Property { get { return ""C.Property""; } } string I1.Property { get { return ""I1.Property""; } } string I2.Property { get { return ""I2.Property""; } } } "; var text2 = @" class Test { static void Main() { C c = new C(); System.Console.WriteLine(c.Property); System.Console.WriteLine(((I1)c).Property); System.Console.WriteLine(((I2)c).Property); } } "; var comp1 = CreateCompilation(text1, assemblyName: "OHI_ExplicitImplProp1"); var comp = CreateCompilation( text2, references: new[] { comp1.EmitToImageReference() }, options: TestOptions.ReleaseExe, assemblyName: "OHI_ExplicitImplProp3"); CompileAndVerify(comp, expectedOutput: @" C.Property I1.Property I2.Property "); } [WorkItem(540431, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540431")] [Fact] public void TestExpImpInterfaceImplementationMetadata() { #region "Impl" var text1 = @"using System; public class CSIMeth02Impl : IMeth02 { #region Explicit void IMeth01.Sub01(params byte[] ary) { Console.Write(""CSS1Exp ""); } void IMeth02.Sub01(sbyte p1, params byte[] ary) { Console.Write(""CSS11Exp ""); } string IMeth01.Func01(params string[] ary) { Console.Write(""CSF1Exp ""); return ary[0]; } string IMeth02.Func01(object p1, params string[] ary) { Console.Write(""CSF11Exp ""); return p1.ToString(); } #endregion #region Implicit public void Sub01(params byte[] ary) { Console.Write(""CSS1Imp ""); } public void Sub01(sbyte p1, params byte[] ary) { Console.Write(""CSS11Imp ""); } public string Func01(params string[] ary) { Console.Write(""CSF1Imp ""); return ary[0]; } public string Func01(object p1, params string[] ary) { Console.Write(""CSF11Imp ""); return p1.ToString(); } #endregion } "; #endregion var text2 = @" class Test { static void Main() { CSIMeth02Impl obj = new CSIMeth02Impl(); obj.Sub01(1, 0, 111); ((IMeth01)obj).Sub01(1, 0, 123); ((IMeth02)obj).Sub01(1, 0, 127); obj.Func01(""A"", ""B""); ((IMeth01)obj).Func01(""A"", ""B""); ((IMeth02)obj).Func01(""A"", ""B""); } } "; var comp1 = CreateCompilation( text1, references: new[] { TestReferences.MetadataTests.InterfaceAndClass.VBInterfaces01 }, assemblyName: "OHI_ExpImpImpl001", options: TestOptions.ReleaseDll); var comp = CreateCompilation( text2, references: new MetadataReference[] { TestReferences.MetadataTests.InterfaceAndClass.VBInterfaces01, new CSharpCompilationReference(comp1) }, assemblyName: "OHI_ExpImpImpl002", options: TestOptions.ReleaseExe); CompileAndVerify(comp, expectedOutput: @"CSS11Imp CSS1Exp CSS11Exp CSF1Imp CSF1Exp CSF11Exp"); } [WorkItem(540431, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540431")] [Fact] public void TestVBInterfaceImplementationMetadata() { var text = @" class Test { static void Main() { VBIMeth02Impl obj = new VBIMeth02Impl(); obj.Sub01(1, 0, 111); ((IMeth01)obj).Sub01(1, 0, 123); ((IMeth02)obj).Sub01(1, 0, 127); obj.Func01(""A"", ""B""); ((IMeth01)obj).Func01(""A"", ""B""); ((IMeth02)obj).Func01(""A"", ""B""); } } "; var asm01 = TestReferences.MetadataTests.InterfaceAndClass.VBInterfaces01; var asm02 = TestReferences.MetadataTests.InterfaceAndClass.VBClasses01; var comp = CreateCompilation( text, references: new[] { asm01, asm02 }, assemblyName: "OHI_ExpImpVBImpl001", options: TestOptions.ReleaseExe); CompileAndVerify(comp, expectedOutput: @"VBS1_V VBS1_V VBS11_OL VBF1_V VBF1_V VBF11"); } [WorkItem(540431, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540431")] [Fact] public void TestExpImpInterfaceImplementationPropMetadata() { #region "Impl" var text1 = @"using System; public class CSIPropImpl : IProp { private string _str; private uint _uint = 22; #region implicit public string ReadOnlyProp { get { return _str; } } public string WriteOnlyProp { set { _str = value; } } public virtual string NormalProp { get { return _str; } set { _str = value; } } public virtual uint get_ReadOnlyPropWithParams(ushort x) { return _uint; } public virtual void set_WriteOnlyPropWithParams(uint x, ulong y) { _uint = x; } public long get_NormalPropWithParams(long x, short y) { return (long)_uint; } public void set_NormalPropWithParams(long x, short y, long z) { _uint = (uint)x; } #endregion #region explicit string IProp.ReadOnlyProp { get { return _str; } } string IProp.WriteOnlyProp { set { _str = value; } } string IProp.NormalProp { get { return _str; } set { _str = value; } } uint IProp.get_ReadOnlyPropWithParams(ushort x) { return _uint; } void IProp.set_WriteOnlyPropWithParams(uint x, ulong y) { _uint = x; } long IProp.get_NormalPropWithParams(long x, short y) { return (long)_uint; } void IProp.set_NormalPropWithParams(long x, short y, long z) { _uint = (uint)x; } #endregion } "; #endregion var text2 = @"using System; class Test { static void Main() { CSIPropImpl obj = new CSIPropImpl(); obj.WriteOnlyProp = ""WriteReadOnly ""; Console.Write(obj.ReadOnlyProp); ((IProp)obj).NormalProp = ""NormProp ""; Console.Write(((IProp)obj).NormalProp); obj.set_NormalPropWithParams(123, 4, 5); Console.Write(obj.get_NormalPropWithParams(11, 22)); ((IProp)obj).set_WriteOnlyPropWithParams(456, 0); Console.Write(((IProp)obj).get_ReadOnlyPropWithParams(789)); } } "; var asm01 = TestReferences.MetadataTests.InterfaceAndClass.VBInterfaces01; var comp1 = CreateCompilation( text1, references: new[] { asm01 }, assemblyName: "OHI_ExpImpPropImpl001", options: TestOptions.ReleaseDll); var comp = CreateCompilation( text2, references: new MetadataReference[] { asm01, new CSharpCompilationReference(comp1) }, assemblyName: "OHI_ExpImpPropImpl002", options: TestOptions.ReleaseExe); CompileAndVerify(comp, expectedOutput: @"WriteReadOnly NormProp 123456"); } [ConditionalFact(typeof(DesktopOnly))] public void TestExplicitImplSignatureMismatches_ParamsAndOptionals() { // Tests: // Replace params with non-params in signature of implemented member (and vice-versa) // Replace optional parameter with non-optional parameter var source = @" using System; using System.Collections.Generic; interface I1<T> { void Method(int a, long b = 2, string c = null, params List<T>[] d); } class Class1 : I1<string> { // Change default value of optional parameter void I1<string>.Method(int a, long b = 3, string c = """", params List<string>[] d) { Console.WriteLine(""Base.Method({0}, {1}, {2})"", a, b, c); } } class Class2 : I1<string> { // Replace optional with non-optional - OK void I1<string>.Method(int a, long b, string c = """", params List<string>[] d) { Console.WriteLine(""Class.Method({0}, {1}, {2})"", a, b, c); } } class Class3 : I1<string> { // Replace non-optional with optional - OK // Omit params and replace with optional - OK void I1<string>.Method(int a = 4, long b = 3, string c = """", List<string>[] d = null) { Console.WriteLine(""Class2.Method({0}, {1}, {2})"", a, b, c); } } class Test { public static void Main() { string[] s1 = new string[]{""a""}; List<string>[] l1 = new List<string>[]{}; I1<string> i1 = new Class1(); i1.Method(1, 2, ""b"", l1); i1 = new Class2(); i1.Method(3, 4, ""c"", l1); i1 = new Class3(); i1.Method(4, 5, ""c"", l1); } }"; var comp = CompileAndVerify(source, expectedOutput: @" Base.Method(1, 2, b) Class.Method(3, 4, c) Class2.Method(4, 5, c)", expectedSignatures: new[] { Signature("Class1", "I1<System.String>.Method", ".method private hidebysig newslot virtual final instance System.Void I1<System.String>.Method(System.Int32 a, [opt] System.Int64 b = 3, [opt] System.String c = \"\", [System.ParamArrayAttribute()] System.Collections.Generic.List`1[System.String][] d) cil managed"), Signature("Class2", "I1<System.String>.Method", ".method private hidebysig newslot virtual final instance System.Void I1<System.String>.Method(System.Int32 a, System.Int64 b, [opt] System.String c = \"\", [System.ParamArrayAttribute()] System.Collections.Generic.List`1[System.String][] d) cil managed"), Signature("Class3", "I1<System.String>.Method", ".method private hidebysig newslot virtual final instance System.Void I1<System.String>.Method([opt] System.Int32 a = 4, [opt] System.Int64 b = 3, [opt] System.String c = \"\", [opt] System.Collections.Generic.List`1[System.String][] d) cil managed") }); comp.VerifyDiagnostics( // (11,40): warning CS1066: The default value specified for parameter 'b' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments // void I1<string>.Method(int a, long b = 3, string c = "", params List<string>[] d) Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "b").WithArguments("b"), // (11,54): warning CS1066: The default value specified for parameter 'c' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments // void I1<string>.Method(int a, long b = 3, string c = "", params List<string>[] d) Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "c").WithArguments("c"), // (17,50): warning CS1066: The default value specified for parameter 'c' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments // void I1<string>.Method(int a, long b, string c = "", params List<string>[] d) Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "c").WithArguments("c"), // (24,32): warning CS1066: The default value specified for parameter 'a' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments // void I1<string>.Method(int a = 4, long b = 3, string c = "", List<string>[] d = null) Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "a").WithArguments("a"), // (24,44): warning CS1066: The default value specified for parameter 'b' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments // void I1<string>.Method(int a = 4, long b = 3, string c = "", List<string>[] d = null) Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "b").WithArguments("b"), // (24,58): warning CS1066: The default value specified for parameter 'c' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments // void I1<string>.Method(int a = 4, long b = 3, string c = "", List<string>[] d = null) Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "c").WithArguments("c"), // (24,81): warning CS1066: The default value specified for parameter 'd' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments // void I1<string>.Method(int a = 4, long b = 3, string c = "", List<string>[] d = null) Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "d").WithArguments("d")); } [WorkItem(540501, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540501")] [Fact] public void TestImplementingGenericNestedInterfaces_Explicit() { // Tests: // Sanity check – use open (T) and closed (C<String>) generic types in the signature of implemented methods // Implement members of generic interface nested inside other generic classes var source = @" using System; using System.Collections.Generic; class Outer<T> { internal class Inner<U> { protected internal interface Interface<V, W> { T Property { set; } void Method<Z>(T a, U[] b, List<V> c, Dictionary<W, Z> d); } internal class Derived1 : Inner<int>.Interface<long, string> { T Outer<T>.Inner<int>.Interface<long, string>.Property { set { Console.WriteLine(""Derived1.set_Property""); } } void Inner<int>.Interface<long, string>.Method<K>(T A, int[] B, List<long> c, Dictionary<string, K> D) { Console.WriteLine(""Derived1.Method""); } internal class Derived2<X, Y> : Outer<X>.Inner<int>.Interface<long, Y> { X Outer<X>.Inner<int>.Interface<long, Y>.Property { set { Console.WriteLine(""Derived2.set_Property""); } } void Outer<X>.Inner<int>.Interface<long, Y>.Method<K>(X A, int[] b, List<long> C, Dictionary<Y, K> d) { Console.WriteLine(""Derived2.Method""); } } } internal class Derived3 : Interface<long, string> { T Inner<U>.Interface<long, string>.Property { set { Console.WriteLine(""Derived3.set_Property""); } } void Outer<T>.Inner<U>.Interface<long, string>.Method<K>(T a, U[] B, List<long> C, Dictionary<string, K> d) { Console.WriteLine(""Derived3.Method""); } } internal class Derived4 : Outer<U>.Inner<T>.Interface<T, U> { U Outer<U>.Inner<T>.Interface<T, U>.Property { set { Console.WriteLine(""Derived4.set_Property""); } } void Outer<U>.Inner<T>.Interface<T, U>.Method<K>(U a, T[] b, List<T> C, Dictionary<U, K> d) { Console.WriteLine(""Derived4.Method""); } internal class Derived5 : Outer<T>.Inner<U>.Interface<U, T> { T Outer<T>.Inner<U>.Interface<U, T>.Property { set { Console.WriteLine(""Derived5.set_Property""); } } void Inner<U>.Interface<U, T>.Method<K>(T a, U[] b, List<U> c, Dictionary<T, K> D) { Console.WriteLine(""Derived5.Method""); } internal class Derived6 : Outer<List<T>>.Inner<U>.Interface<List<U>, T> { List<T> Outer<List<T>>.Inner<U>.Interface<List<U>, T>.Property { set { Console.WriteLine(""Derived6.set_Property""); } } void Outer<List<T>>.Inner<U>.Interface<List<U>, T>.Method<K>(List<T> AA, U[] b, List<List<U>> c, Dictionary<T, K> d) { Console.WriteLine(""Derived6.Method""); } } } } } } class Test { public static void Main() { Outer<string>.Inner<int>.Interface<long, string> i = new Outer<string>.Inner<int>.Derived1(); i.Property = """"; i.Method<string>("""", new int[]{}, new List<long>(), new Dictionary<string,string>()); i = new Outer<string>.Inner<int>.Derived1.Derived2<string, string>(); i.Property = """"; i.Method<string>("""", new int[] { }, new List<long>(), new Dictionary<string, string>()); i = new Outer<string>.Inner<int>.Derived3(); i.Property = """"; i.Method<string>("""", new int[] { }, new List<long>(), new Dictionary<string, string>()); Outer<int>.Inner<string>.Interface<string, int> i2 = new Outer<string>.Inner<int>.Derived4(); i2.Property = 1; i2.Method<string>(1, new string[] { }, new List<string>(), new Dictionary<int, string>()); Outer<string>.Inner<int>.Interface<int, string> i3 = new Outer<string>.Inner<int>.Derived4.Derived5(); i3.Property = """"; i3.Method<string>("""", new int[] { }, new List<int>(), new Dictionary<string, string>()); Outer<List<int>>.Inner<List<string>>.Interface<List<List<string>>, int> i4 = new Outer<int>.Inner<List<string>>.Derived4.Derived5.Derived6(); i4.Property = new List<int>(); i4.Method<List<long>>(new List<int>(), new List<string>[]{}, new List<List<List<string>>>(), new Dictionary<int, List<long>>()); } }"; var comp = CompileAndVerify(source, expectedOutput: @" Derived1.set_Property Derived1.Method Derived2.set_Property Derived2.Method Derived3.set_Property Derived3.Method Derived4.set_Property Derived4.Method Derived5.set_Property Derived5.Method Derived6.set_Property Derived6.Method", expectedSignatures: new[] { Signature("Outer`1+Inner`1+Derived1", "Outer<T>.Inner<System.Int32>.Interface<System.Int64,System.String>.set_Property", ".method private hidebysig newslot specialname virtual final instance System.Void Outer<T>.Inner<System.Int32>.Interface<System.Int64,System.String>.set_Property(T value) cil managed"), Signature("Outer`1+Inner`1+Derived1", "Outer<T>.Inner<System.Int32>.Interface<System.Int64,System.String>.Method", ".method private hidebysig newslot virtual final instance System.Void Outer<T>.Inner<System.Int32>.Interface<System.Int64,System.String>.Method<K>(T A, System.Int32[] B, System.Collections.Generic.List`1[System.Int64] c, System.Collections.Generic.Dictionary`2[System.String,K] D) cil managed"), Signature("Outer`1+Inner`1+Derived1+Derived2`2", "Outer<X>.Inner<System.Int32>.Interface<System.Int64,Y>.set_Property", ".method private hidebysig newslot specialname virtual final instance System.Void Outer<X>.Inner<System.Int32>.Interface<System.Int64,Y>.set_Property(X value) cil managed"), Signature("Outer`1+Inner`1+Derived1+Derived2`2", "Outer<X>.Inner<System.Int32>.Interface<System.Int64,Y>.Method", ".method private hidebysig newslot virtual final instance System.Void Outer<X>.Inner<System.Int32>.Interface<System.Int64,Y>.Method<K>(X A, System.Int32[] b, System.Collections.Generic.List`1[System.Int64] C, System.Collections.Generic.Dictionary`2[Y,K] d) cil managed"), Signature("Outer`1+Inner`1+Derived3", "Outer<T>.Inner<U>.Interface<System.Int64,System.String>.set_Property", ".method private hidebysig newslot specialname virtual final instance System.Void Outer<T>.Inner<U>.Interface<System.Int64,System.String>.set_Property(T value) cil managed"), Signature("Outer`1+Inner`1+Derived3", "Outer<T>.Inner<U>.Interface<System.Int64,System.String>.Method", ".method private hidebysig newslot virtual final instance System.Void Outer<T>.Inner<U>.Interface<System.Int64,System.String>.Method<K>(T a, U[] B, System.Collections.Generic.List`1[System.Int64] C, System.Collections.Generic.Dictionary`2[System.String,K] d) cil managed"), Signature("Outer`1+Inner`1+Derived4", "Outer<U>.Inner<T>.Interface<T,U>.set_Property", ".method private hidebysig newslot specialname virtual final instance System.Void Outer<U>.Inner<T>.Interface<T,U>.set_Property(U value) cil managed"), Signature("Outer`1+Inner`1+Derived4", "Outer<U>.Inner<T>.Interface<T,U>.Method", ".method private hidebysig newslot virtual final instance System.Void Outer<U>.Inner<T>.Interface<T,U>.Method<K>(U a, T[] b, System.Collections.Generic.List`1[T] C, System.Collections.Generic.Dictionary`2[U,K] d) cil managed"), Signature("Outer`1+Inner`1+Derived4+Derived5", "Outer<T>.Inner<U>.Interface<U,T>.set_Property", ".method private hidebysig newslot specialname virtual final instance System.Void Outer<T>.Inner<U>.Interface<U,T>.set_Property(T value) cil managed"), Signature("Outer`1+Inner`1+Derived4+Derived5", "Outer<T>.Inner<U>.Interface<U,T>.Method", ".method private hidebysig newslot virtual final instance System.Void Outer<T>.Inner<U>.Interface<U,T>.Method<K>(T a, U[] b, System.Collections.Generic.List`1[U] c, System.Collections.Generic.Dictionary`2[T,K] D) cil managed"), Signature("Outer`1+Inner`1+Derived4+Derived5+Derived6", "Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>,T>.set_Property", ".method private hidebysig newslot specialname virtual final instance System.Void Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>,T>.set_Property(System.Collections.Generic.List`1[T] value) cil managed"), Signature("Outer`1+Inner`1+Derived4+Derived5+Derived6", "Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>,T>.Method", ".method private hidebysig newslot virtual final instance System.Void Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>,T>.Method<K>(System.Collections.Generic.List`1[T] AA, U[] b, System.Collections.Generic.List`1[System.Collections.Generic.List`1[U]] c, System.Collections.Generic.Dictionary`2[T,K] d) cil managed") }); comp.VerifyDiagnostics(); // No Errors } [WorkItem(540501, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540501")] [Fact] public void TestImplementingGenericNestedInterfaces_Explicit_HideTypeParameter() { // Tests: // Explicitly implement generic methods on generic interfaces – test case where type parameter // on method hides the type parameter on class (both in interface and in implementing type) var source = @" using System; using System.Collections.Generic; class Outer<T> { internal class Inner<U> { protected internal interface Interface<V, W> { void Method<Z>(T a, U[] b, List<V> c, Dictionary<W, Z> d); void Method<V, W>(T a, U[] b, List<V> c, Dictionary<W, W> d); } internal class Derived1<X, Y> : Outer<long>.Inner<int>.Interface<long, Y> { void Outer<long>.Inner<int>.Interface<long, Y>.Method<X>(long A, int[] b, List<long> C, Dictionary<Y, X> d) { Console.WriteLine(""Derived1.Method`1""); } void Outer<long>.Inner<int>.Interface<long, Y>.Method<X, Y>(long A, int[] b, List<X> C, Dictionary<Y, Y> d) { Console.WriteLine(""Derived1.Method`2""); } } } } class Test { public static void Main() { Outer<long>.Inner<int>.Interface<long, string> i = new Outer<long>.Inner<int>.Derived1<string, string>(); i.Method<string>(1, new int[]{}, new List<long>(), new Dictionary<string, string>()); i.Method<string, int>(1, new int[]{}, new List<string>(), new Dictionary<int, int>()); } }"; var comp = CompileAndVerify(source, expectedOutput: @" Derived1.Method`1 Derived1.Method`2", expectedSignatures: new[] { Signature("Outer`1+Inner`1+Derived1`2", "Outer<System.Int64>.Inner<System.Int32>.Interface<System.Int64,Y>.Method", ".method private hidebysig newslot virtual final instance System.Void Outer<System.Int64>.Inner<System.Int32>.Interface<System.Int64,Y>.Method<X>(System.Int64 A, System.Int32[] b, System.Collections.Generic.List`1[System.Int64] C, System.Collections.Generic.Dictionary`2[Y,X] d) cil managed"), Signature("Outer`1+Inner`1+Derived1`2", "Outer<System.Int64>.Inner<System.Int32>.Interface<System.Int64,Y>.Method", ".method private hidebysig newslot virtual final instance System.Void Outer<System.Int64>.Inner<System.Int32>.Interface<System.Int64,Y>.Method<X, Y>(System.Int64 A, System.Int32[] b, System.Collections.Generic.List`1[X] C, System.Collections.Generic.Dictionary`2[Y,Y] d) cil managed"), }); comp.VerifyDiagnostics( // (11,25): warning CS0693: Type parameter 'V' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Interface<V, W>' Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "V").WithArguments("V", "Outer<T>.Inner<U>.Interface<V, W>"), // (11,28): warning CS0693: Type parameter 'W' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Interface<V, W>' Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "W").WithArguments("W", "Outer<T>.Inner<U>.Interface<V, W>"), // (15,67): warning CS0693: Type parameter 'X' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Derived1<X, Y>' Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "X").WithArguments("X", "Outer<T>.Inner<U>.Derived1<X, Y>"), // (19,67): warning CS0693: Type parameter 'X' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Derived1<X, Y>' Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "X").WithArguments("X", "Outer<T>.Inner<U>.Derived1<X, Y>"), // (19,70): warning CS0693: Type parameter 'Y' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Derived1<X, Y>' Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "Y").WithArguments("Y", "Outer<T>.Inner<U>.Derived1<X, Y>")); } [ConditionalFact(typeof(ClrOnly), Reason = "https://github.com/mono/mono/issues/10837")] public void TestExplicitImplementationInBaseGenericType() { // Tests: // Implement I<string> explicitly in base class and I<int> explicitly in derived class – // assuming I<string> and I<int> have members with same signature (i.e. members // that don't depend on generic-ness of the interface) test which (base / derived class) // members are invoked when calling through each interface var source = @" using System; interface Interface<T> { void Method(T x); void Method(); } class Base<T> : Interface<T> { void Interface<T>.Method() { Console.WriteLine(""Base.Method()""); } void Interface<T>.Method(T x) { Console.WriteLine(""Base.Method(T)""); } } class Derived<U, V> : Base<int>, Interface<U> { void Interface<U>.Method() { Console.WriteLine(""Derived`2.Method()""); } public void Method(int x) { Console.WriteLine(""Derived`2.Method(int)""); } void Interface<U>.Method(U x) { Console.WriteLine(""Derived`2.Method(U)""); } public void Method(V x) { Console.WriteLine(""Derived`2.Method(V)""); } } class Derived : Derived<int, string>, Interface<string> { void Interface<string>.Method() { Console.WriteLine(""Derived.Method()""); } void Interface<string>.Method(string x) { Console.WriteLine(""Derived.Method(string)""); } } class Test { public static void Main() { Interface<string> i = new Derived<string, int>(); i.Method(""""); i.Method(); Interface<int> j = new Derived<string, int>(); j.Method(1); j.Method(); i = new Derived(); i.Method(""""); i.Method(); j = new Derived(); j.Method(1); j.Method(); } }"; var comp = CompileAndVerify(source, expectedOutput: @" Derived`2.Method(U) Derived`2.Method() Base.Method(T) Base.Method() Derived.Method(string) Derived.Method() Derived`2.Method(U) Derived`2.Method()"); comp.VerifyDiagnostics(); // No errors } [ConditionalFact(typeof(ClrOnly), Reason = "https://github.com/mono/mono/issues/10837")] public void TestExplicitImplementationInBaseGenericType2() { // Tests: // Variation of TestExplicitImplementationInBaseGenericType with re-implementation var source = @" using System; interface Interface<T> { void Method(T x); void Method(); } class Base<T> : Interface<T> { void Interface<T>.Method() { Console.WriteLine(""Base.Method()""); } void Interface<T>.Method(T x) { Console.WriteLine(""Base.Method(T)""); } } class Derived<U, V> : Base<int>, Interface<U> { void Interface<U>.Method() { Console.WriteLine(""Derived`2.Method()""); } void Interface<U>.Method(U x) { Console.WriteLine(""Derived`2.Method(U)""); } public virtual void Method(V x) { Console.WriteLine(""Derived`2.Method(V)""); } } class Derived : Derived<int, string>, Interface<string>, Interface<int> { void Interface<string>.Method() { Console.WriteLine(""Derived.Method()""); } void Interface<string>.Method(string x) { Console.WriteLine(""Derived.Method(string)""); } void Interface<int>.Method(int x) { Console.WriteLine(""Derived.Method(int)""); } } class Test { public static void Main() { Interface<string> i = new Derived<string, int>(); i.Method(""""); i.Method(); Interface<int> j = new Derived<string, int>(); j.Method(1); j.Method(); i = new Derived(); i.Method(""""); i.Method(); j = new Derived(); j.Method(1); j.Method(); } }"; var comp = CompileAndVerify(source, expectedOutput: @" Derived`2.Method(U) Derived`2.Method() Base.Method(T) Base.Method() Derived.Method(string) Derived.Method() Derived.Method(int) Derived`2.Method()"); comp.VerifyDiagnostics(); // No errors } [Fact] public void TestImplementAmbiguousSignaturesExplicitly() { // Tests: // Explicitly implement multiple base interface members with same signatures // but different return types / ref / out / params var source = @" using System; interface I1 { int P { set; } void M1(long x); void M2(long x); void M3(long x); void M4(ref long x); void M5(out long x); void M6(ref long x); void M7(out long x); void M8(params long[] x); void M9(long[] x); } interface I2 : I1 { } interface I3 : I2 { new long P { set; } new int M1(long x); // Return type void M2(ref long x); // Add ref void M3(out long x); // Add out void M4(long x); // Omit ref void M5(long x); // Omit out void M6(out long x); // Toggle ref to out void M7(ref long x); // Toggle out to ref new void M8(long[] x); // Omit params new void M9(params long[] x); // Add params } class Test : I3 { int I1.P { set { Console.WriteLine(""I1.P""); } } long I3.P { set { Console.WriteLine(""I3.P""); } } void I1.M1(long x) { Console.WriteLine(""I1.M1""); } void I1.M2(long x) { Console.WriteLine(""I1.M2""); } void I1.M3(long x) { Console.WriteLine(""I1.M3""); } void I1.M4(ref long x) { Console.WriteLine(""I1.M4""); } void I1.M5(out long x) { x = 0; Console.WriteLine(""I1.M5""); } void I1.M6(ref long x) { Console.WriteLine(""I1.M6""); } void I1.M7(out long x) { x = 0; Console.WriteLine(""I1.M7""); } void I1.M8(params long[] x) { Console.WriteLine(""I1.M8""); } void I1.M9(long[] x) { Console.WriteLine(""I1.M9""); } int I3.M1(long x) { Console.WriteLine(""I3.M1""); return 0; } void I3.M2(ref long x) { Console.WriteLine(""I3.M2""); } void I3.M3(out long x) { x = 0; Console.WriteLine(""I3.M3""); } void I3.M4(long x) { Console.WriteLine(""I3.M4""); } void I3.M5(long x) { Console.WriteLine(""I3.M5""); } void I3.M6(out long x) { x = 0; Console.WriteLine(""I3.M6""); } void I3.M7(ref long x) { Console.WriteLine(""I3.M7""); } void I3.M8(long[] x) { Console.WriteLine(""I3.M8""); } void I3.M9(params long[] x) { Console.WriteLine(""I3.M9""); } public static void Main() { I3 i = new Test(); long x = 1; i.M1(x); i.M2(x); i.M2(ref x); i.M3(x); i.M3(out x); i.M4(x); i.M4(ref x); i.M5(x); i.M5(out x); i.M6(out x); i.M6(ref x); i.M7(ref x); i.M7(out x); i.M8(new long[] { x, x, x }); i.M8(x, x, x); i.M9(new long[] { x, x, x }); i.M9(x, x, x); i.P = 1; I1 j = i; j.M1(x); j.M2(x); j.M3(x); j.M4(ref x); j.M5(out x); j.M6(ref x); j.M7(out x); j.M8(new long[] { x, x, x }); j.M8(x, x, x); j.M9(new long[] { x, x, x }); j.P = 1; } }"; CompileAndVerify(source, expectedOutput: @" I3.M1 I1.M2 I3.M2 I1.M3 I3.M3 I3.M4 I1.M4 I3.M5 I1.M5 I3.M6 I1.M6 I3.M7 I1.M7 I3.M8 I1.M8 I3.M9 I3.M9 I3.P I1.M1 I1.M2 I1.M3 I1.M4 I1.M5 I1.M6 I1.M7 I1.M8 I1.M8 I1.M9 I1.P").VerifyDiagnostics(); // No errors } [WorkItem(543426, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543426")] [Fact] public void TestExplicitlyImplementInterfaceNestedInGenericType() { // Tests: // Variation of TestExplicitImplementationInBaseGenericType with re-implementation var source = @" class Outer<T> { interface IInner { void M(T t); } class Inner : IInner { void IInner.M(T t) { } } } "; var comp = CompileAndVerify(source, expectedSignatures: new[] { Signature("Outer`1+IInner", "M", ".method public hidebysig newslot abstract virtual instance System.Void M(T t) cil managed"), Signature("Outer`1+Inner", "Outer<T>.IInner.M", ".method private hidebysig newslot virtual final instance System.Void Outer<T>.IInner.M(T t) cil managed"), }); comp.VerifyDiagnostics(); // No errors } [WorkItem(598052, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/598052")] [Fact] public void TestExternAliasInName() { var libSource = @" public interface I { void M(); int P { get; set; } event System.Action E; } "; var source = @" extern alias Q; class C : Q::I { void Q::I.M() { } int Q::I.P { get { return 0; } set { } } event System.Action Q::I.E { add { } remove { } } } "; var libComp = CreateCompilation(libSource); libComp.VerifyDiagnostics(); var comp = CreateCompilation(source, new[] { new CSharpCompilationReference(libComp, aliases: ImmutableArray.Create("Q")) }); comp.VerifyDiagnostics(); var classC = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C"); var classCMembers = classC.GetMembers(); // The alias is preserved, in case a similar interface is implemented from another aliased assembly. AssertEx.All(classCMembers.Select(m => m.Name), name => name == WellKnownMemberNames.InstanceConstructorName || name.StartsWith("Q::I.", StringComparison.Ordinal)); AssertEx.All(classCMembers.Select(m => m.MetadataName), metadataName => metadataName == WellKnownMemberNames.InstanceConstructorName || metadataName.StartsWith("Q::I.", StringComparison.Ordinal)); AssertEx.None(classCMembers.Select(m => m.ToString()), id => id.Contains("Q")); AssertEx.None(classCMembers.Select(m => m.GetDocumentationCommentId()), id => id.Contains("Q")); } [WorkItem(598052, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/598052")] [Fact] public void TestImplementMultipleExternAliasInterfaces() { var libSource = @" public interface I { void M(); int P { get; set; } event System.Action E; } "; var source = @" extern alias A; extern alias B; class C : A::I, B::I { void A::I.M() { } int A::I.P { get { return 0; } set { } } event System.Action A::I.E { add { } remove { } } void B::I.M() { } int B::I.P { get { return 0; } set { } } event System.Action B::I.E { add { } remove { } } } "; var libComp1 = CreateCompilation(libSource, assemblyName: "lib1"); libComp1.VerifyDiagnostics(); var libComp2 = CreateCompilation(libSource, assemblyName: "lib2"); libComp2.VerifyDiagnostics(); // Same reference, two aliases. var comp1 = CreateCompilation(source, new[] { new CSharpCompilationReference(libComp1, aliases: ImmutableArray.Create("A")), new CSharpCompilationReference(libComp1, aliases: ImmutableArray.Create("B")) }); comp1.VerifyDiagnostics( // (5,17): error CS0528: 'I' is already listed in interface list // class C : A::I, B::I Diagnostic(ErrorCode.ERR_DuplicateInterfaceInBaseList, "B::I").WithArguments("I"), // (5,7): error CS8646: 'I.E' is explicitly implemented more than once. // class C : A::I, B::I Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C").WithArguments("I.E").WithLocation(5, 7), // (5,7): error CS8646: 'I.P' is explicitly implemented more than once. // class C : A::I, B::I Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C").WithArguments("I.P").WithLocation(5, 7), // (5,7): error CS8646: 'I.M()' is explicitly implemented more than once. // class C : A::I, B::I Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C").WithArguments("I.M()").WithLocation(5, 7)); // Two assemblies with the same content, two aliases. var comp2 = CreateCompilation(source, new[] { new CSharpCompilationReference(libComp1, aliases: ImmutableArray.Create("A")), new CSharpCompilationReference(libComp2, aliases: ImmutableArray.Create("B")) }); var verifier2 = CompileAndVerify(comp2, expectedSignatures: new[] { Signature("C", "A::I.M", ".method private hidebysig newslot virtual final instance System.Void A::I.M() cil managed"), Signature("C", "A::I.get_P", ".method private hidebysig newslot specialname virtual final instance System.Int32 A::I.get_P() cil managed"), Signature("C", "A::I.set_P", ".method private hidebysig newslot specialname virtual final instance System.Void A::I.set_P(System.Int32 value) cil managed"), Signature("C", "A::I.add_E", ".method private hidebysig newslot specialname virtual final instance System.Void A::I.add_E(System.Action value) cil managed"), Signature("C", "A::I.remove_E", ".method private hidebysig newslot specialname virtual final instance System.Void A::I.remove_E(System.Action value) cil managed"), Signature("C", "B::I.M", ".method private hidebysig newslot virtual final instance System.Void B::I.M() cil managed"), Signature("C", "B::I.get_P", ".method private hidebysig newslot specialname virtual final instance System.Int32 B::I.get_P() cil managed"), Signature("C", "B::I.set_P", ".method private hidebysig newslot specialname virtual final instance System.Void B::I.set_P(System.Int32 value) cil managed"), Signature("C", "B::I.add_E", ".method private hidebysig newslot specialname virtual final instance System.Void B::I.add_E(System.Action value) cil managed"), Signature("C", "B::I.remove_E", ".method private hidebysig newslot specialname virtual final instance System.Void B::I.remove_E(System.Action value) cil managed"), }); // Simple verification that the test infrastructure supports such methods. var testData = verifier2.TestData; var pair = testData.Methods.Single(m => m.Key.Name == "A::I.M"); pair.Value.VerifyIL(@" { // Code size 1 (0x1) .maxstack 0 IL_0000: ret }"); } } }