View difference between Paste ID: ZSz37Cu6 and 1vzGR82f
SHOW: | | - or go back to the newest paste.
1
using System;
2
using System.Diagnostics;
3
using System.Runtime.InteropServices;
4
5
public struct TaggedUnion<T1,T2>
6
{
7
	public TaggedUnion(T1 value) { _union=new _Union{Type1=value}; _id=1; }
8
	public TaggedUnion(T2 value) { _union=new _Union{Type2=value}; _id=2; }
9
10
	public T1 Type1 { get{ if(_id!=1)_TypeError(1); return _union.Type1; } set{ _union.Type1=value; _id=1; } }
11
	public T2 Type2 { get{ if(_id!=2)_TypeError(2); return _union.Type2; } set{ _union.Type2=value; _id=2; } }
12
13
	public static explicit operator T1(TaggedUnion<T1,T2> value) { return value.Type1; }
14
	public static explicit operator T2(TaggedUnion<T1,T2> value) { return value.Type2; }
15
	public static implicit operator TaggedUnion<T1,T2>(T1 value) { return new TaggedUnion<T1,T2>(value); }
16
	public static implicit operator TaggedUnion<T1,T2>(T2 value) { return new TaggedUnion<T1,T2>(value); }
17
18
	public byte Tag {get{ return _id; }}
19
20
	public Type GetUnionType()
21
	{switch(_id){
22
		case 1:  return typeof(T1);
23
		case 2:  return typeof(T2);
24
		default: return typeof(void);
25
	}}
26
27
	public override string ToString()
28
	{switch(_id){
29
		case 1:  return _union.Type1.ToString();
30
		case 2:  return _union.Type2.ToString();
31
		default: return "void";
32
	}}
33
34
	_Union _union;
35
	byte _id;
36
	void _TypeError(byte id) { throw new InvalidCastException(/* todo */); }
37
38
	[StructLayout(LayoutKind.Explicit)]
39
	struct _Union
40
	{
41
		[FieldOffset(0)] public T1 Type1;
42
		[FieldOffset(0)] public T2 Type2;
43
	}
44
}
45
46
public static class TaggedUnion
47
{
48
	// System.TypeLoadException: Could not load type '_Union' because generic types cannot have explicit layout.
49
	public static void test()
50
	{
51
		TaggedUnion<int, double> foo = 1;
52
53
		Debug.Assert(foo.GetUnionType() == typeof(int));
54
		{ int bar = (int) foo; }
55
		try {
56
			double bar = (double)foo;
57
			Debug.Assert(false);
58
		} catch (InvalidCastException) {}
59
60
		foo = 1.0;
61
62
		Debug.Assert(foo.GetUnionType() == typeof(double));
63
		{ double bar = (double) foo; }
64
65
		try { Console.WriteLine((int)foo); Debug.Assert(false); }
66
		catch (InvalidCastException) {}
67
	}
68
}