using System; using System.Collections.Generic; using System.Reflection; namespace GenericSharingTest { public delegate int IntVoidDelegate (); public class ClassA {} public class ClassB {} public class ClassC {} public class GenExc : Exception {} public class NonGen { public static int field = 123; public static void doThrow () { throw new GenExc (); } } public class GenBi { public static int field = 123; public static float floatField = 1.0f; public static int staticMethod (int x) { return x + field; } public static void staticVoidMethod (int x) { field = x; } public static float staticFloatMethod () { return floatField; } public static long staticLongMethod (long x) { return x + field; } public static GenStruct staticValueMethod (int x) { return new GenStruct (x); } } public struct GenStruct { public static int staticField; public int field; public int dummy1; public int dummy2; public int dummy3; public GenStruct (int f) { field = f; dummy1 = dummy2 = dummy3 = 0; } public int method (int x) { return x + field; } } public interface IGen { T[] iMethod (); void voidIMethod (int x); long longIMethod (long x); float floatIMethod (); GenStruct valueIMethod (int x); } public class IGenImpl : IGen { public int field; public T[] iMethod () { return new T[3]; } public void voidIMethod (int x) { field = x; } public long longIMethod (long x) { return x + 1; } public float floatIMethod () { return 1.0f; } public GenStruct valueIMethod (int x) { return new GenStruct (x); } } public class GenA { public static T[] arr; static GenA () { arr = new T [3]; } public GenA () {} public GenA newGen () { return new GenA (); } public GenA newGenInt () { return new GenA (); } public int getGenField () { return GenB.field; } public int getNonGenField () { return NonGen.field; } public int getGenStructStaticField () { return GenStruct.staticField; } public T[] getArr () { return arr; } public T[] newArr () { return new T [3]; } public GenA[] newSelfArr () { return new GenA [3]; } public GenB>[] newArrNested () { /* GenB>[] arr = null; for (int i = 0; i < 10000000; ++i) arr = new GenB> [3]; */ return new GenB> [3]; } public int hash (T obj) { return obj.GetHashCode (); } public T ident (T obj) { return obj; } public T cast (Object obj) { return (T)obj; } public GenStruct structCast (Object obj) { return (GenStruct)obj; } public Type ldtokenT () { return typeof (T); } public Type ldtokenIGenT () { return typeof (IGen); } public Type ldtokenGenAIGenT () { return typeof (GenA>); } public Type ldtokenGenB () { return typeof (GenB<>); } public GenStruct? makeNullable (Object obj) { return (GenStruct?)obj; } public object unmakeNullable (GenStruct? obj) { return (object)obj; } public void except () { try { NonGen.doThrow (); } catch (GenExc) { //Console.WriteLine("exception thrown"); } } public static void staticExcept () { try { NonGen.doThrow (); } catch (GenExc) { Console.WriteLine("exception thrown and caught"); } } public static int staticField = 54321; public static int staticMethod () { return staticField; } public static int staticMethodCaller () { return staticMethod (); } public static float staticFloatField = 1.0f; public static float staticFloatMethod () { return staticFloatField; } public static int staticBiCaller (int x) { return GenBi.staticMethod (x); } public static void staticBiVoidCaller (int x) { GenBi.staticVoidMethod (x); } public static float staticBiFloatCaller () { return GenBi.staticFloatMethod (); } public static GenStruct staticBiValueCaller (int x) { return GenBi.staticValueMethod (x); } public static int staticSharedBiCaller (int x) { return GenBi.staticMethod (x); } public static void staticSharedBiVoidCaller (int x) { GenBi.staticVoidMethod (x); } public static float staticSharedBiFloatCaller () { return GenBi.staticFloatMethod (); } public static GenStruct staticSharedBiValueCaller (int x) { return GenBi.staticValueMethod (x); } public static long staticBiLongCaller (long x) { return GenBi.staticLongMethod (x); } public int structCaller (int x) { GenStruct> gs = new GenStruct> (123); return gs.method (x); } public T[] callInterface (IGen ig) { return ig.iMethod (); } public void callVoidInterface (IGen ig, int x) { ig.voidIMethod (x); } public long callLongInterface (IGen ig, long x) { return ig.longIMethod (x); } public float callFloatInterface (IGen ig) { return ig.floatIMethod (); } public GenStruct callValueInterface (IGen ig, int x) { return ig.valueIMethod (x); } } public class GenB { public static int field = 123; } public class GenC { public static int field ; static GenC () { field = 1234; } } public class StaticTest { static int stat; public StaticTest (int x) { stat = x; } public int getStat () { return stat; } public int getOtherStat () { return StaticTest.stat; } public int getGenCStat () { return GenC.field; } } public class GenADeriv : GenA { public static int otherField = 123; } public class GenABDeriv : GenA> { public T[] newDerivArr () { return new T [3]; } } public class NonGenUser where T : NonGen { public int getNonGenField () { return NonGen.field; } } public class AccessTest { private static int field = 123; public int getOtherField () { return AccessTest.field; } } public class VirtualTest { public virtual T[] newArr () { return new T [3]; } } public class VirtualTestDeriv : VirtualTest { public override T[] newArr () { return new T [4]; } } public class VirtualTestCaller { public T[] doCall (VirtualTest vt) { return vt.newArr (); } } public class MyCons { public T car; public MyCons cdr; public static void printCar (T _car) { Console.WriteLine ("car " + _car.ToString () /* + " cdr " + _cdr.ToString () */); } public MyCons (T _car, MyCons _cdr) { //printCar (_car); car = _car; cdr = _cdr; } public static MyCons returnList (MyCons l) { return l; } public static MyCons returnCdr (MyCons cons) { return returnList(cons.cdr); } } public class MyPair { public N n; public M m; public MyPair (N _n, M _m) { n = _n; m = _m; } } public class MyDict { public MyPair p; public MyDict (N n, M m) { p = new MyPair (n, m); } } public class RGCTXTest { public GenA[] newAArr () { return new GenA [3]; } } public class RGCTXTestSubA : RGCTXTest { public GenB[] newBArr () { return new GenB [3]; } } public class RGCTXTestSubB : RGCTXTest { public GenC[] newCArr () { return new GenC [3]; } } public class RGCTXTestSubASub : RGCTXTestSubA { } public class RGCTXTestSubASubSub : RGCTXTestSubASub { public GenC[] newCArr () { return new GenC [3]; } } public class main { delegate void ActionDelegate (); static bool haveError = false; static void error (string message) { haveError = true; Console.WriteLine (message); } static void typeCheck (String method, Object obj, Type t) { if (obj.GetType () != t) error ("object from " + method + " should have type " + t.ToString () + " but has type " + obj.GetType ().ToString ()); } static int callStaticMethod () { return GenA.staticMethod (); } static void checkException (String method, ActionDelegate action) where T : Exception { try { try { action (); } catch (T) { return; } } catch (Exception exc) { error ("method " + method + " should have thrown " + typeof (T).ToString () + " but did throw " + exc); } } public static void work (T obj, bool mustCatch) { EqualityComparer comp = EqualityComparer.Default; GenA ga = new GenA (); typeCheck ("newGen", ga.newGen (), typeof (GenA)); typeCheck ("newGenInt", ga.newGenInt (), typeof (GenA)); typeCheck ("getArr", ga.getArr (), typeof (T[])); typeCheck ("newArr", ga.newArr (), typeof (T[])); typeCheck ("newSelfArr", ga.newSelfArr (), typeof (GenA[])); //ga.newArrNested (); typeCheck ("newArrNested", ga.newArrNested (), typeof (GenB>[])); if (ga.getGenField () != 123) error ("getGenField"); if (ga.getNonGenField () != 123) error ("getNonGenField"); GenStruct.staticField = 321; if (ga.getGenStructStaticField () != 321) error ("getGenStructStaticField"); GenStruct.staticField = -1; ga.hash (obj); if (!comp.Equals (ga.ident (obj), obj)) error ("ident"); if (!comp.Equals (ga.cast (obj), obj)) error ("cast"); if (typeof (T).IsValueType) { checkException ("cast null value", delegate { ga.cast (null); }); } else { if (ga.cast (null) != null) error ("cast null"); } GenStruct genstructt = new GenStruct (453); if (ga.structCast ((object)genstructt).field != 453) error ("structCast"); checkException ("structCast null", delegate { ga.structCast (null); }); if (ga.makeNullable ((object)genstructt).Value.field != 453) error ("makeNullable"); if (ga.makeNullable (null) != null) error ("makeNullable null"); if (ga.ldtokenT () != typeof (T)) error ("ldtokenT"); if (ga.ldtokenIGenT () != typeof (IGen)) error ("ldtokenIGenT"); if (ga.ldtokenGenAIGenT () != typeof (GenA>)) error ("ldtokenGenAIGenT"); if (ga.ldtokenGenB () != typeof (GenB<>)) error ("ldtokenGenB"); if (callStaticMethod () != 54321) error ("staticMethod"); GenBi.field = 123; if (GenA.staticBiCaller (123) != 246) error ("staticBiCaller"); GenA.staticBiVoidCaller (1234); if (GenBi.field != 1234) error ("staticBiVoidCaller"); if (GenA.staticBiFloatCaller () != 1.0f) error ("staticBiFloatCaller"); if (GenA.staticBiLongCaller (123) != 123 + 1234) error ("staticBiLongCaller"); GenStruct gs = GenA.staticBiValueCaller (987); if (gs.field != 987) error ("staticBiValueCaller"); GenBi.field = 123; if (GenA.staticSharedBiCaller (123) != 246) error ("staticSharedBiCaller"); GenA.staticSharedBiVoidCaller (1234); if (GenBi.field != 1234) error ("staticSharedBiVoidCaller"); if (GenA.staticSharedBiFloatCaller () != 1.0f) error ("staticSharedBiFloatCaller"); GenStruct gss = GenA.staticSharedBiValueCaller (987); if (gss.field != 987) error ("staticSharedBiValueCaller"); IntVoidDelegate ivdel = new IntVoidDelegate (GenA.staticMethod); if (ivdel () != 54321) error ("staticMethod delegate"); Type gatype = typeof (GenA); MethodInfo staticMethodInfo = gatype.GetMethod ("staticMethod"); if ((Convert.ToInt32 (staticMethodInfo.Invoke (null, null))) != 54321) error ("staticMethod reflection"); if (GenA.staticMethodCaller () != 54321) error ("staticMethodCaller"); if (GenA.staticFloatMethod () != 1.0) error ("staticFloatMethod"); if (ga.structCaller (234) != 357) error ("structCaller"); IGenImpl igi = new IGenImpl (); typeCheck ("callInterface", ga.callInterface (igi), typeof (T[])); if (ga.callLongInterface (igi, 345) != 346) error ("callLongInterface"); GenStruct gst = ga.callValueInterface (igi, 543); if (gst.field != 543) error ("callValueInterface"); ga.callVoidInterface (igi, 654); if (igi.field != 654) error ("callVoidInterface"); if (ga.callFloatInterface (igi) != 1.0f) error ("callFloatInterface"); new GenADeriv (); if (mustCatch) { checkException> ("except", delegate { ga.except (); }); checkException> ("staticExcept", delegate { GenA.staticExcept (); }); } else { ga.except (); GenA.staticExcept (); } MyDict dtb = new MyDict (obj, new ClassB ()); typeCheck ("MyPair", dtb.p, typeof (MyPair)); GenABDeriv gabd = new GenABDeriv (); typeCheck ("GenABDeriv.newArr", gabd.newArr (), typeof (GenB[])); typeCheck ("GenABDeriv.newDerivArr", gabd.newDerivArr (), typeof (T[])); RGCTXTest rt = new RGCTXTest (); RGCTXTestSubA rtsa = new RGCTXTestSubA (); RGCTXTestSubB rtsb = new RGCTXTestSubB (); RGCTXTestSubASub rtsas = new RGCTXTestSubASub (); RGCTXTestSubASubSub rtsass = new RGCTXTestSubASubSub (); typeCheck ("rtsass.newCArr", rtsass.newCArr (), typeof (GenC[])); typeCheck ("rgsa.newBArr", rtsa.newBArr (), typeof (GenB[])); typeCheck ("rg.newAArr", rt.newAArr (), typeof (GenA[])); typeCheck ("rgsb.newCArr", rtsb.newCArr (), typeof (GenC[])); /* repeat all for each class */ typeCheck ("rtsass.newCArr", rtsass.newCArr (), typeof (GenC[])); typeCheck ("rtsass.newBArr", rtsass.newBArr (), typeof (GenB[])); typeCheck ("rtsass.newAArr", rtsass.newAArr (), typeof (GenA[])); typeCheck ("rtsas.newBArr", rtsas.newBArr (), typeof (GenB[])); typeCheck ("rtsas.newAArr", rtsas.newAArr (), typeof (GenA[])); typeCheck ("rtsa.newBArr", rtsa.newBArr (), typeof (GenB[])); typeCheck ("rtsa.newAArr", rtsa.newAArr (), typeof (GenA[])); typeCheck ("rtsb.newCArr", rtsb.newCArr (), typeof (GenC[])); typeCheck ("rtsb.newAArr", rtsb.newAArr (), typeof (GenA[])); typeCheck ("rt.newAArr", rt.newAArr (), typeof (GenA[])); } public static void virtualTest (VirtualTest vt, int len) { VirtualTestCaller vtc = new VirtualTestCaller (); T[] arr = vtc.doCall (vt); typeCheck ("virtualTest", arr, typeof (T[])); if (arr.Length != len) error ("virtualTest length"); } public static void listTest () { MyCons ls = new MyCons ("abc", null); MyCons cdr = MyCons.returnCdr (ls); if (cdr != null) error ("cdr is not null"); } public static int Main () { work (new ClassA (), false); work (new ClassB (), true); work (new ClassB (), true); work (new ClassC (), true); work> (new GenA (), true); work (new int[3], true); work (123, true); work (123, true); work?> (new GenStruct (123), true); work?> (null, true); StaticTest sa = new StaticTest (1234); StaticTest sb = new StaticTest (2345); if (sa.getStat () != 1234) error ("getStat"); if (sb.getStat () != 2345) error ("getStat"); if (sa.getOtherStat () != 0) error ("getOtherStat"); if (sa.getGenCStat () != 1234) error ("getGenCStat A"); if (sb.getGenCStat () != 1234) error ("getGenCStat B"); NonGenUser ngu = new NonGenUser (); if (ngu.getNonGenField () != 123) error ("getNonGenField"); AccessTest ata = new AccessTest (); if (ata.getOtherField () != 123) error ("getOtherField"); VirtualTest vta = new VirtualTest (); VirtualTest vtb = new VirtualTestDeriv (); virtualTest (vta, 3); virtualTest (vtb, 4); listTest (); if (haveError) return 1; return 0; } } }