using System; using System.Threading; using System.Runtime.Serialization; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Tests { [TestClass] public class TestGeneric : BaseTest { volatile Version m_version; volatile EventHandler m_eventHandler; public override void TestMain() { TestGenericReplace(); TestGenericRecursive(); TestGenericVariance(); TestGenericOverload(); TestByRefValue(); TestByRefArray(); TestGenericOverload2(); TestGenericInterface2(); TestGenericOverload3(); TestGenericMethodWithEnum(); TestGenericByRef(); } // // TestGenericReplace // static Func CreateVersionObject = () => new Version(); static void EventCallback(object sender, EventArgs e) {} void TestGenericReplace() { #pragma warning disable 0420 Interlocked.CompareExchange(ref m_eventHandler, EventCallback, null); var version1 = LazyInitializer.EnsureInitialized(ref m_version, CreateVersionObject); var version2 = LazyInitializer.EnsureInitialized(ref m_version, CreateVersionObject); Console.WriteLine("TestGenericReplace? " + object.ReferenceEquals(version1, version2)); #pragma warning restore 0420 } // // TestGenericRecursive // public class Base { protected void PrintType() { Console.WriteLine(typeof(T)); } } public class Base2 : Base { } private sealed class Recursive : Base[]> { private readonly Base[] _items; internal Recursive(Base[] itemsCopy) : base() { _items = itemsCopy; base.PrintType(); } } void TestGenericRecursive() { new Recursive(new Base[2]); } // // TestGenericVariance // public interface InterfaceVariant { TOut Method(TIn arg); } void TestGenericVariance() { var t0 = typeof(InterfaceVariant); int ti = 0; foreach (var t1 in new Type[] { typeof(InterfaceVariant), typeof(InterfaceVariant), typeof(InterfaceVariant), typeof(InterfaceVariant), typeof(InterfaceVariant), typeof(InterfaceVariant), typeof(InterfaceVariant), typeof(InterfaceVariant), typeof(InterfaceVariant), typeof(InterfaceVariant), }) { Console.Write((ti++) + "=" + t1.IsAssignableFrom(t0) + ";"); } Console.WriteLine(); Console.WriteLine("Exception is ISerializable? " + ((new Exception()) is ISerializable)); } // // TestGenericOverload // public abstract class Base5 { public abstract TOutput Invoke(TInput value); } public class Derived5 : Base5 { public override string Invoke(Version value) => value.ToString(); } void TestGenericOverload() { var result = (new Derived5()).Invoke(new Version()); Console.WriteLine($"Result type {result.GetType()} value {result}"); } // // TestByRef // void TestByRefValue() { int a = 1; Console.Write(a); f1(ref a); Console.Write(a); f2(ref a); Console.Write(a); void f1(ref int a) => a *= 2; void f2(ref T a) => a = (T) (object) (((int) (object) a) * 2); } void TestByRefArray() { var a = new int[1]; Console.Write(a.Length); f1(ref a); Console.Write(a.Length); f2(ref a); Console.WriteLine(a.Length); void f1(ref int[] a) => a = new int[2]; void f2(ref T[] a) => a = new T[3]; } // // test generic resolution // class MyTest { static void F1() { new MyTest>(); } } // // // public interface I1 { int Get(T v); } public interface I2 { int Get(T v); } class MyOv1 : I1, I2 { public virtual int Get(T1 v) => 1; public virtual int Get(T2 v) => 2; } class MyOv2 : MyOv1 { public override int Get(T1 v) => 3; public override int Get(T2 v) => 4; } void TestGenericOverload2() { var a = new MyOv1(); Console.Write(a.Get(1)); Console.Write(a.Get(true)); Console.Write(((I1) a).Get(true)); Console.Write(((I2) a).Get(1)); var b = new MyOv2(); Console.Write(b.Get(1)); Console.WriteLine(b.Get(true)); } // // TestGenericInterface // interface AaaIfc { void Method(T a); } class AaaImpl : AaaIfc { public void Method(T a) => Console.WriteLine(typeof(T) + "," + typeof(S)); } void TestGenericInterface2() { AaaIfc c = new AaaImpl(); c.Method(false); } // // TestGenericOverload3 // public abstract class CccB1 { public abstract void DoIt(ref T1 a, ref T2 b); } public class CccC1 : CccB1 { public override void DoIt(ref T1 a, ref int b) => Console.Write("OK1 "); } public class CccC2 : CccB1 { public override void DoIt(ref T1 a, ref Version b) => Console.Write("OK2 "); } public class CccC3 : CccB1 { public override void DoIt(ref T1 a, ref object b) => Console.Write("OK3 "); } public class CccC4 : CccB1{ public override void DoIt(ref T1 a, ref T2 b) => Console.Write("OK4 "); } void TestGenericOverload3() { bool bFalse = false; int iZero = 0; Version vZero = null; object oZero = null; CccB1 c1 = new CccC1(); CccB1 c2 = new CccC2(); CccB1 c3 = new CccC3(); CccB1c4 = new CccC4(); c1.DoIt(ref bFalse, ref iZero); c2.DoIt(ref bFalse, ref vZero); c3.DoIt(ref bFalse, ref oZero); c4.DoIt(ref bFalse, ref oZero); Console.WriteLine(); } // // TestGenericMethodWithEnum // void TestGenericMethodWithEnum() { Console.WriteLine(TestGenericMethodWithEnum_(TypeCode.Int32)); T TestGenericMethodWithEnum_(T a) { Console.Write(a); Console.Write(","); return a; } } // // TestGenericByRef // void TestGenericByRef() { var guid = new Guid("12345678123456781234567812345678"); Helper(ref guid, true); void Helper(ref T arg, bool cond) where T : IFormattable { Console.WriteLine(arg.ToString(cond ? "" : "D", null)); } } } }