bluebonnet/Tests/src/TestGeneric.cs
2021-08-05 07:59:29 +03:00

284 lines
8.0 KiB
C#

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<Version> 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<Version>(ref m_version, CreateVersionObject);
var version2 = LazyInitializer.EnsureInitialized<Version>(ref m_version, CreateVersionObject);
Console.WriteLine("TestGenericReplace? " + object.ReferenceEquals(version1, version2));
#pragma warning restore 0420
}
//
// TestGenericRecursive
//
public class Base<T>
{
protected void PrintType() { Console.WriteLine(typeof(T)); }
}
public class Base2<T> : Base<T> { }
private sealed class Recursive<U> : Base<Base<U>[]>
{
private readonly Base<U>[] _items;
internal Recursive(Base<U>[] itemsCopy) : base()
{
_items = itemsCopy;
base.PrintType();
}
}
void TestGenericRecursive()
{
new Recursive<string>(new Base<string>[2]);
}
//
// TestGenericVariance
//
public interface InterfaceVariant<in TIn, out TOut>
{
TOut Method(TIn arg);
}
void TestGenericVariance()
{
var t0 = typeof(InterfaceVariant<Exception, Exception>);
int ti = 0;
foreach (var t1 in new Type[] {
typeof(InterfaceVariant<object, Exception>),
typeof(InterfaceVariant<Exception, Exception>),
typeof(InterfaceVariant<SystemException, Exception>),
typeof(InterfaceVariant<ISerializable, Exception>),
typeof(InterfaceVariant<Exception, object>),
typeof(InterfaceVariant<Exception, SystemException>),
typeof(InterfaceVariant<Exception, ISerializable>),
typeof(InterfaceVariant<object, object>),
typeof(InterfaceVariant<SystemException, SystemException>),
typeof(InterfaceVariant<ISerializable, ISerializable>),
})
{
Console.Write((ti++) + "=" + t1.IsAssignableFrom(t0) + ";");
}
Console.WriteLine();
Console.WriteLine("Exception is ISerializable? " + ((new Exception()) is ISerializable));
}
//
// TestGenericOverload
//
public abstract class Base5<TInput,TOutput>
{
public abstract TOutput Invoke(TInput value);
}
public class Derived5 : Base5<Version,string>
{
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<int>(ref a);
Console.Write(a);
void f1(ref int a) => a *= 2;
void f2<T>(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<int>(ref a);
Console.WriteLine(a.Length);
void f1(ref int[] a) => a = new int[2];
void f2<T>(ref T[] a) => a = new T[3];
}
//
// test generic resolution
//
class MyTest<T1,T2>
{
static void F1<S1>()
{
new MyTest<S1,ValueTuple<T1,T2>>();
}
}
//
//
//
public interface I1<T> { int Get(T v); }
public interface I2<T> { int Get(T v); }
class MyOv1<T1,T2> : I1<T2>, I2<T1>
{
public virtual int Get(T1 v) => 1;
public virtual int Get(T2 v) => 2;
}
class MyOv2<T1,T2> : MyOv1<T2,T1>
{
public override int Get(T1 v) => 3;
public override int Get(T2 v) => 4;
}
void TestGenericOverload2()
{
var a = new MyOv1<int,bool>();
Console.Write(a.Get(1));
Console.Write(a.Get(true));
Console.Write(((I1<bool>) a).Get(true));
Console.Write(((I2<int>) a).Get(1));
var b = new MyOv2<int,bool>();
Console.Write(b.Get(1));
Console.WriteLine(b.Get(true));
}
//
// TestGenericInterface
//
interface AaaIfc<T>
{
void Method<S>(T a);
}
class AaaImpl<U,T> : AaaIfc<T>
{
public void Method<S>(T a) => Console.WriteLine(typeof(T) + "," + typeof(S));
}
void TestGenericInterface2()
{
AaaIfc<bool> c = new AaaImpl<char,bool>();
c.Method<int>(false);
}
//
// TestGenericOverload3
//
public abstract class CccB1<T1,T2> { public abstract void DoIt(ref T1 a, ref T2 b); }
public class CccC1<T1> : CccB1<T1,int> { public override void DoIt(ref T1 a, ref int b) => Console.Write("OK1 "); }
public class CccC2<T1> : CccB1<T1,Version> { public override void DoIt(ref T1 a, ref Version b) => Console.Write("OK2 "); }
public class CccC3<T1> : CccB1<T1,object> { public override void DoIt(ref T1 a, ref object b) => Console.Write("OK3 "); }
public class CccC4<T0,T2,T1> : CccB1<T1,T2>{ 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<bool,int> c1 = new CccC1<bool>();
CccB1<bool,Version> c2 = new CccC2<bool>();
CccB1<bool,object> c3 = new CccC3<bool>();
CccB1<bool,object>c4 = new CccC4<int,object,bool>();
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>(TypeCode.Int32));
T TestGenericMethodWithEnum_<T>(T a)
{
Console.Write(a);
Console.Write(",");
return a;
}
}
//
// TestGenericByRef
//
void TestGenericByRef()
{
var guid = new Guid("12345678123456781234567812345678");
Helper<Guid>(ref guid, true);
void Helper<T>(ref T arg, bool cond) where T : IFormattable
{
Console.WriteLine(arg.ToString(cond ? "" : "D", null));
}
}
}
}