diff --git a/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs b/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs
index b12ba8915..4f9edfc30 100644
--- a/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs
+++ b/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs
@@ -20,6 +20,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Linq;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.Semantics;
@@ -106,6 +107,37 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
return conversions.ExplicitConversion(from2, to2);
}
+ ///
+ /// Converts a constant expression (e.g. an integer literal) to the target type.
+ ///
+ Conversion ConstantConversion(object value, Type to)
+ {
+ IType fromType = compilation.FindType(value.GetType());
+ IType to2 = compilation.FindType(to).AcceptVisitor(new ReplaceSpecialTypesVisitor());
+ return conversions.ImplicitConversion(new ConstantResolveResult(fromType, value), to2);
+ }
+
+ ///
+ /// Builds a MethodGroupResolveResult from all methods named
+ /// in (as if the expression were "instance.M") and
+ /// converts it to .
+ ///
+ Conversion MethodGroupConversion(Type declaringType, string methodName, Type delegateType,
+ ResolveResult targetResult = null, IMethod[] extensionMethods = null)
+ {
+ IType declaring = compilation.FindType(declaringType);
+ var mgrr = new MethodGroupResolveResult(
+ targetResult ?? new ResolveResult(declaring), methodName,
+ new[] { new MethodListWithDeclaringType(declaring, declaring.GetMethods(m => m.Name == methodName)) },
+ null);
+ if (extensionMethods != null)
+ {
+ mgrr.extensionMethods = new List> { new List(extensionMethods) };
+ }
+ IType dt = compilation.FindType(delegateType).AcceptVisitor(new ReplaceSpecialTypesVisitor());
+ return conversions.ImplicitConversion(mgrr, dt);
+ }
+
[Test]
public void IdentityConversions()
{
@@ -688,161 +720,123 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
Assert.That(BetterConversion(typeof(sbyte), typeof(int?), typeof(uint?)), Is.EqualTo(0));
}
- /* TODO: we should probably revive these tests somehow
[Test]
public void ExpansiveInheritance()
{
- var a = new DefaultUnresolvedTypeDefinition(string.Empty, "A");
- var b = new DefaultUnresolvedTypeDefinition(string.Empty, "B");
- // interface A
- a.Kind = TypeKind.Interface;
- a.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.TypeDefinition, 0, "U") { Variance = VarianceModifier.Contravariant });
+ // interface A { }
// interface B : A>> { }
- b.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.TypeDefinition, 0, "X"));
- b.BaseTypes.Add(new ParameterizedTypeReference(
- a, new[] { new ParameterizedTypeReference(
- a, new [] { new ParameterizedTypeReference(
- b, new [] { new TypeParameterReference(SymbolKind.TypeDefinition, 0) }
- ) } ) }));
-
- ICompilation compilation = TypeSystemHelper.CreateCompilation(a, b);
- ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a.FullTypeName);
- ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b.FullTypeName);
-
- IType type1 = new ParameterizedType(resolvedB, new[] { compilation.FindType(KnownTypeCode.Double) });
- IType type2 = new ParameterizedType(resolvedA, new[] { new ParameterizedType(resolvedB, new[] { compilation.FindType(KnownTypeCode.String) }) });
+ // Finding a conversion B -> A> must terminate even though
+ // the base-type substitution keeps producing ever-larger types.
+ ITypeDefinition a = compilation.FindType(typeof(ExpansiveInheritanceTestCases.A<>)).GetDefinition();
+ ITypeDefinition b = compilation.FindType(typeof(ExpansiveInheritanceTestCases.B<>)).GetDefinition();
+
+ IType type1 = new ParameterizedType(b, ImmutableArray.Create(compilation.FindType(KnownTypeCode.Double)));
+ IType type2 = new ParameterizedType(a, ImmutableArray.Create(
+ new ParameterizedType(b, ImmutableArray.Create(compilation.FindType(KnownTypeCode.String)))));
Assert.That(!conversions.ImplicitConversion(type1, type2).IsValid);
}
[Test]
public void ImplicitTypeParameterConversion()
{
- string program = @"using System;
-class Test {
- public void M(T t) where T : U {
- U u = $t$;
- }
-}";
- Assert.AreEqual(C.BoxingConversion, GetConversion(program));
+ // void M(T t) where T : U => "U u = t;" is a boxing conversion
+ // (e.g. T = int, U = object)
+ ITypeParameter u = new DefaultTypeParameter(compilation, SymbolKind.Method, 1, "U");
+ ITypeParameter t = new DefaultTypeParameter(compilation, SymbolKind.Method, 0, "T", constraints: new[] { u });
+ Assert.That(conversions.ImplicitConversion(t, u), Is.EqualTo(C.BoxingConversion));
}
[Test]
public void InvalidImplicitTypeParameterConversion()
{
- string program = @"using System;
-class Test {
- public void M(T t) where U : T {
- U u = $t$;
- }
-}";
- Assert.AreEqual(C.None, GetConversion(program));
+ // void M(T t) where U : T => "U u = t;" is invalid
+ // (the constraint points the wrong way)
+ ITypeParameter t = new DefaultTypeParameter(compilation, SymbolKind.Method, 0, "T");
+ ITypeParameter u = new DefaultTypeParameter(compilation, SymbolKind.Method, 1, "U", constraints: new[] { t });
+ Assert.That(conversions.ImplicitConversion(t, u), Is.EqualTo(C.None));
}
[Test]
public void ImplicitTypeParameterArrayConversion()
{
- string program = @"using System;
-class Test {
- public void M(T[] t) where T : U {
- U[] u = $t$;
- }
-}";
- // invalid, e.g. T=int[], U=object[]
- Assert.AreEqual(C.None, GetConversion(program));
+ // void M(T[] t) where T : U => "U[] u = t;" is invalid
+ // (e.g. T = int, U = object: int[] is not convertible to object[])
+ ITypeParameter u = new DefaultTypeParameter(compilation, SymbolKind.Method, 1, "U");
+ ITypeParameter t = new DefaultTypeParameter(compilation, SymbolKind.Method, 0, "T", constraints: new[] { u });
+ Assert.That(conversions.ImplicitConversion(new ArrayType(compilation, t), new ArrayType(compilation, u)), Is.EqualTo(C.None));
}
[Test]
public void ImplicitTypeParameterConversionWithClassConstraint()
{
- string program = @"using System;
-class Test {
- public void M(T t) where T : class, U where U : class {
- U u = $t$;
- }
-}";
- Assert.AreEqual(C.ImplicitReferenceConversion, GetConversion(program));
+ // void M(T t) where T : class, U where U : class => "U u = t;" is a reference conversion
+ ITypeParameter u = new DefaultTypeParameter(compilation, SymbolKind.Method, 1, "U", hasReferenceTypeConstraint: true);
+ ITypeParameter t = new DefaultTypeParameter(compilation, SymbolKind.Method, 0, "T", hasReferenceTypeConstraint: true, constraints: new[] { u });
+ Assert.That(conversions.ImplicitConversion(t, u), Is.EqualTo(C.ImplicitReferenceConversion));
}
[Test]
public void ImplicitTypeParameterArrayConversionWithClassConstraint()
{
- string program = @"using System;
-class Test {
- public void M(T[] t) where T : class, U where U : class {
- U[] u = $t$;
- }
-}";
- Assert.AreEqual(C.ImplicitReferenceConversion, GetConversion(program));
+ // void M(T[] t) where T : class, U where U : class => "U[] u = t;" is a
+ // covariant array conversion (both are known to be reference types)
+ ITypeParameter u = new DefaultTypeParameter(compilation, SymbolKind.Method, 1, "U", hasReferenceTypeConstraint: true);
+ ITypeParameter t = new DefaultTypeParameter(compilation, SymbolKind.Method, 0, "T", hasReferenceTypeConstraint: true, constraints: new[] { u });
+ Assert.That(conversions.ImplicitConversion(new ArrayType(compilation, t), new ArrayType(compilation, u)), Is.EqualTo(C.ImplicitReferenceConversion));
}
[Test]
public void ImplicitTypeParameterConversionWithClassConstraintOnlyOnT()
{
- string program = @"using System;
-class Test {
- public void M(T t) where T : class, U {
- U u = $t$;
- }
-}";
- Assert.AreEqual(C.ImplicitReferenceConversion, GetConversion(program));
+ // void M(T t) where T : class, U => "U u = t;" is a reference conversion
+ // (T is known to be a reference type, so no boxing is involved)
+ ITypeParameter u = new DefaultTypeParameter(compilation, SymbolKind.Method, 1, "U");
+ ITypeParameter t = new DefaultTypeParameter(compilation, SymbolKind.Method, 0, "T", hasReferenceTypeConstraint: true, constraints: new[] { u });
+ Assert.That(conversions.ImplicitConversion(t, u), Is.EqualTo(C.ImplicitReferenceConversion));
}
[Test]
public void ImplicitTypeParameterArrayConversionWithClassConstraintOnlyOnT()
{
- string program = @"using System;
-class Test {
- public void M(T[] t) where T : class, U {
- U[] u = $t$;
- }
-}";
- Assert.AreEqual(C.ImplicitReferenceConversion, GetConversion(program));
+ // void M(T[] t) where T : class, U => "U[] u = t;" is a covariant array conversion
+ ITypeParameter u = new DefaultTypeParameter(compilation, SymbolKind.Method, 1, "U");
+ ITypeParameter t = new DefaultTypeParameter(compilation, SymbolKind.Method, 0, "T", hasReferenceTypeConstraint: true, constraints: new[] { u });
+ Assert.That(conversions.ImplicitConversion(new ArrayType(compilation, t), new ArrayType(compilation, u)), Is.EqualTo(C.ImplicitReferenceConversion));
}
[Test]
public void MethodGroupConversion_Void()
{
- string program = @"using System;
-delegate void D();
-class Test {
- D d = $M$;
- public static void M() {}
-}";
- var c = GetConversion(program);
+ // delegate void D();
+ // D d = M; with public static void M() {}
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.VoidStatic), "M",
+ typeof(MethodGroupConversionTestCases.DVoid));
Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
Assert.That(!c.DelegateCapturesFirstArgument);
- Assert.IsNotNull(c.Method);
+ Assert.That(c.Method, Is.Not.Null);
}
[Test]
public void MethodGroupConversion_Void_InstanceMethod()
{
- string program = @"using System;
-delegate void D();
-class Test {
- D d;
- public void M() {
- d = $M$;
- }
-}";
- var c = GetConversion(program);
+ // delegate void D();
+ // D d = M; with public void M() {} (instance method)
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.VoidInstance), "M",
+ typeof(MethodGroupConversionTestCases.DVoid));
Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
Assert.That(c.DelegateCapturesFirstArgument);
- Assert.IsNotNull(c.Method);
+ Assert.That(c.Method, Is.Not.Null);
}
[Test]
public void MethodGroupConversion_MatchingSignature()
{
- string program = @"using System;
-delegate object D(int argument);
-class Test {
- D d = $M$;
- public static object M(int argument) {}
-}";
- var c = GetConversion(program);
+ // delegate object D(int argument);
+ // D d = M; with public static object M(int argument) {...}
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.ReturnObjectFromInt), "M",
+ typeof(MethodGroupConversionTestCases.DObjInt));
Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
}
@@ -850,13 +844,12 @@ class Test {
[Test]
public void MethodGroupConversion_InvalidReturnType()
{
- string program = @"using System;
-delegate object D(int argument);
-class Test {
- D d = $M$;
- public static int M(int argument) {}
-}";
- var c = GetConversion(program);
+ // delegate object D(int argument);
+ // D d = M; with public static int M(int argument) {...}
+ // int -> object is a boxing conversion, not an identity/reference conversion,
+ // so the method is not delegate-compatible.
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.ReturnIntFromInt), "M",
+ typeof(MethodGroupConversionTestCases.DObjInt));
Assert.That(!c.IsValid);
Assert.That(c.IsMethodGroupConversion);
}
@@ -864,13 +857,10 @@ class Test {
[Test]
public void MethodGroupConversion_CovariantReturnType()
{
- string program = @"using System;
-delegate object D(int argument);
-class Test {
- D d = $M$;
- public static string M(int argument) {}
-}";
- var c = GetConversion(program);
+ // delegate object D(int argument);
+ // D d = M; with public static string M(int argument) {...}
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.ReturnStringFromInt), "M",
+ typeof(MethodGroupConversionTestCases.DObjInt));
Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
}
@@ -878,13 +868,10 @@ class Test {
[Test]
public void MethodGroupConversion_RefArgumentTypesEqual()
{
- string program = @"using System;
-delegate void D(ref object o);
-class Test {
- D d = $M$;
- public static void M(ref object o) {}
-}";
- var c = GetConversion(program);
+ // delegate void D(ref object o);
+ // D d = M; with public static void M(ref object o) {}
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.RefObjParam), "M",
+ typeof(MethodGroupConversionTestCases.DRefObj));
Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
}
@@ -892,66 +879,54 @@ class Test {
[Test]
public void MethodGroupConversion_RefArgumentObjectVsDynamic()
{
- string program = @"using System;
-delegate void D(ref object o);
-class Test {
- D d = $M$;
- public static void M(ref dynamic o) {}
-}";
- var c = GetConversion(program);
- Assert.That(!c.IsValid);
+ // delegate void D(ref object o);
+ // D d = M; with public static void M(ref dynamic o) {}
+ // ref parameters require an identity conversion, and object <-> dynamic IS an
+ // identity conversion, so this is valid (Roslyn accepts it; the original
+ // NRefactory test expected invalid, which matched pre-Roslyn csc behavior).
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.RefDynamicParam), "M",
+ typeof(MethodGroupConversionTestCases.DRefObj));
+ Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
}
[Test]
public void MethodGroupConversion_RefVsOut()
{
- string program = @"using System;
-delegate void D(ref object o);
-class Test {
- D d = $M$;
- public static void M(out object o) {}
-}";
- var c = GetConversion(program);
+ // delegate void D(ref object o);
+ // D d = M; with public static void M(out object o) {...}
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.OutObjParam), "M",
+ typeof(MethodGroupConversionTestCases.DRefObj));
Assert.That(!c.IsValid);
}
[Test]
public void MethodGroupConversion_RefVsNormal()
{
- string program = @"using System;
-delegate void D(ref object o);
-class Test {
- D d = $M$;
- public static void M(object o) {}
-}";
- var c = GetConversion(program);
+ // delegate void D(ref object o);
+ // D d = M; with public static void M(object o) {}
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.ObjParam), "M",
+ typeof(MethodGroupConversionTestCases.DRefObj));
Assert.That(!c.IsValid);
}
[Test]
public void MethodGroupConversion_NormalVsOut()
{
- string program = @"using System;
-delegate void D(object o);
-class Test {
- D d = $M$;
- public static void M(out object o) {}
-}";
- var c = GetConversion(program);
+ // delegate void D(object o);
+ // D d = M; with public static void M(out object o) {...}
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.OutObjParam), "M",
+ typeof(MethodGroupConversionTestCases.DObj));
Assert.That(!c.IsValid);
}
[Test]
public void MethodGroupConversion_MatchingNormalParameter()
{
- string program = @"using System;
-delegate void D(object o);
-class Test {
- D d = $M$;
- public static void M(object o) {}
-}";
- var c = GetConversion(program);
+ // delegate void D(object o);
+ // D d = M; with public static void M(object o) {}
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.ObjParam), "M",
+ typeof(MethodGroupConversionTestCases.DObj));
Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
}
@@ -959,13 +934,11 @@ class Test {
[Test]
public void MethodGroupConversion_IdentityConversion()
{
- string program = @"using System;
-delegate void D(object o);
-class Test {
- D d = $M$;
- public static void M(dynamic o) {}
-}";
- var c = GetConversion(program);
+ // delegate void D(object o);
+ // D d = M; with public static void M(dynamic o) {}
+ // object -> dynamic is an identity conversion, so M is delegate-compatible.
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.DynamicParam), "M",
+ typeof(MethodGroupConversionTestCases.DObj));
Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
}
@@ -973,95 +946,77 @@ class Test {
[Test]
public void MethodGroupConversion_Contravariance()
{
- string program = @"using System;
-delegate void D(string o);
-class Test {
- D d = $M$;
- public static void M(object o) {}
-}";
- var c = GetConversion(program);
+ // delegate void D(string o);
+ // D d = M; with public static void M(object o) {}
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.ObjParam), "M",
+ typeof(MethodGroupConversionTestCases.DStr));
Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
-
}
[Test, Ignore("Not sure if this conversion should be valid or not... NR and mcs both accept it as valid, csc treats it as invalid")]
public void MethodGroupConversion_NoContravarianceDynamic()
{
- string program = @"using System;
-delegate void D(string o);
-class Test {
- D d = $M$;
- public static void M(dynamic o) {}
-}";
- var c = GetConversion(program);
- //Assert.IsFrue(c.IsValid);
+ // delegate void D(string o);
+ // D d = M; with public static void M(dynamic o) {}
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.DynamicParam), "M",
+ typeof(MethodGroupConversionTestCases.DStr));
+ //Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
}
[Test]
public void MethodGroupConversion_ExactMatchIsBetter()
{
- string program = @"using System;
-class Test {
- delegate void D(string a);
- D d = $M$;
- static void M(object x) {}
- static void M(string x = null) {}
-}";
- var c = GetConversion(program);
+ // delegate void D(string a);
+ // D d = M; with static void M(object x) {} and static void M(string x = null) {}
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.OverloadObjectOrOptionalString), "M",
+ typeof(MethodGroupConversionTestCases.DStr));
Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
- Assert.AreEqual("System.String", c.Method.Parameters.Single().Type.FullName);
+ Assert.That(c.Method.Parameters.Single().Type.FullName, Is.EqualTo("System.String"));
}
[Test]
public void MethodGroupConversion_CannotLeaveOutOptionalParameters()
{
- string program = @"using System;
-class Test {
- delegate void D(string a);
- D d = $M$;
- static void M(object x) {}
- static void M(string x, string y = null) {}
-}";
- var c = GetConversion(program);
+ // delegate void D(string a);
+ // D d = M; with static void M(object x) {} and static void M(string x, string y = null) {}
+ // The two-parameter overload cannot bind to a one-parameter delegate.
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.OverloadObjectOrStringPlusOptional), "M",
+ typeof(MethodGroupConversionTestCases.DStr));
Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
- Assert.AreEqual("System.Object", c.Method.Parameters.Single().Type.FullName);
+ Assert.That(c.Method.Parameters.Single().Type.FullName, Is.EqualTo("System.Object"));
}
[Test]
public void MethodGroupConversion_CannotUseExpandedParams()
{
- string program = @"using System;
-class Test {
- delegate void D(string a);
- D d = $M$;
- static void M(object x) {}
- static void M(params string[] x) {}
-}";
- var c = GetConversion(program);
+ // delegate void D(string a);
+ // D d = M; with static void M(object x) {} and static void M(params string[] x) {}
+ // The params overload only matches in expanded form, which method group
+ // conversions do not use.
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.OverloadObjectOrParamsString), "M",
+ typeof(MethodGroupConversionTestCases.DStr));
Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
- Assert.AreEqual("System.Object", c.Method.Parameters.Single().Type.FullName);
+ Assert.That(c.Method.Parameters.Single().Type.FullName, Is.EqualTo("System.Object"));
}
[Test]
public void MethodGroupConversion_ExtensionMethod()
{
- string program = @"using System;
-static class Ext {
- public static void M(this string s, int x) {}
-}
-class Test {
- delegate void D(int a);
- void F() {
- string s = """";
- D d = $s.M$;
- }
-}";
- var c = GetConversion(program);
+ // static class Ext { public static void M(this string s, int x) {} }
+ // delegate void D(int a);
+ // string s = ""; D d = s.M;
+ IType stringType = compilation.FindType(KnownTypeCode.String);
+ IMethod extensionMethod = compilation.FindType(typeof(MethodGroupConversionExt))
+ .GetMethods(m => m.Name == "M").Single();
+ var c = MethodGroupConversion(typeof(string), "M",
+ typeof(MethodGroupConversionTestCases.DInt),
+ targetResult: new ResolveResult(stringType),
+ extensionMethods: new[] { extensionMethod });
Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
Assert.That(c.DelegateCapturesFirstArgument);
@@ -1070,17 +1025,11 @@ class Test {
[Test]
public void MethodGroupConversion_ExtensionMethodUsedAsStaticMethod()
{
- string program = @"using System;
-static class Ext {
- public static void M(this string s, int x) {}
-}
-class Test {
- delegate void D(string s, int a);
- void F() {
- D d = $Ext.M$;
- }
-}";
- var c = GetConversion(program);
+ // static class Ext { public static void M(this string s, int x) {} }
+ // delegate void D(string s, int a);
+ // D d = Ext.M;
+ var c = MethodGroupConversion(typeof(MethodGroupConversionExt), "M",
+ typeof(MethodGroupConversionTestCases.DStrInt));
Assert.That(c.IsValid);
Assert.That(c.IsMethodGroupConversion);
Assert.That(!c.DelegateCapturesFirstArgument);
@@ -1089,102 +1038,63 @@ class Test {
[Test]
public void MethodGroupConversion_ObjectToDynamic()
{
- string program = @"using System;
-class Test {
- public void F(object o) {}
- public void M() {
- Action x = $F$;
- }
-}";
- var c = GetConversion(program);
+ // Action x = F; with public void F(object o) {}
+ var c = MethodGroupConversion(typeof(MethodGroupConversionTestCases.ObjParamInstance), "F",
+ typeof(Action));
Assert.That(c.IsValid);
}
[Test]
public void MethodGroupConversion_ObjectToDynamicGenericArgument()
{
- string program = @"using System;
-using System.Collections.Generic;
-class Test {
- public void F(List