Advertisement
Guest User

TaggedUnion

a guest
Nov 4th, 2014
514
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement