Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Diagnostics;
- using System.Runtime.InteropServices;
- public struct TaggedUnion<T1,T2>
- {
- public TaggedUnion(T1 value) { _union=new _Union{Type1=value}; _id=1; }
- public TaggedUnion(T2 value) { _union=new _Union{Type2=value}; _id=2; }
- public T1 Type1 { get{ if(_id!=1)_TypeError(1); return _union.Type1; } set{ _union.Type1=value; _id=1; } }
- public T2 Type2 { get{ if(_id!=2)_TypeError(2); return _union.Type2; } set{ _union.Type2=value; _id=2; } }
- public static explicit operator T1(TaggedUnion<T1,T2> value) { return value.Type1; }
- public static explicit operator T2(TaggedUnion<T1,T2> value) { return value.Type2; }
- public static implicit operator TaggedUnion<T1,T2>(T1 value) { return new TaggedUnion<T1,T2>(value); }
- public static implicit operator TaggedUnion<T1,T2>(T2 value) { return new TaggedUnion<T1,T2>(value); }
- public byte Tag {get{ return _id; }}
- public Type GetUnionType()
- {switch(_id){
- case 1: return typeof(T1);
- case 2: return typeof(T2);
- default: return typeof(void);
- }}
- public override string ToString()
- {switch(_id){
- case 1: return _union.Type1.ToString();
- case 2: return _union.Type2.ToString();
- default: return "void";
- }}
- _Union _union;
- byte _id;
- void _TypeError(byte id) { throw new InvalidCastException(/* todo */); }
- [StructLayout(LayoutKind.Explicit)]
- struct _Union
- {
- [FieldOffset(0)] public T1 Type1;
- [FieldOffset(0)] public T2 Type2;
- }
- }
- public static class TaggedUnion
- {
- // System.TypeLoadException: Could not load type '_Union' because generic types cannot have explicit layout.
- public static void test()
- {
- TaggedUnion<int, double> foo = 1;
- Debug.Assert(foo.GetUnionType() == typeof(int));
- { int bar = (int) foo; }
- try {
- double bar = (double)foo;
- Debug.Assert(false);
- } catch (InvalidCastException) {}
- foo = 1.0;
- Debug.Assert(foo.GetUnionType() == typeof(double));
- { double bar = (double) foo; }
- try { Console.WriteLine((int)foo); Debug.Assert(false); }
- catch (InvalidCastException) {}
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement