#define DEBUG using System; using Gregor.Core; namespace Gregor { public static class Start { public static void Main(string[] args){ Dev.TraceCallback = Dev.ConsoleTraceCallback; try{ Run(args); }catch(Exception ex){ Dev.Trace(ex.Message); } } private static void Run(string[] args){ Limbo name = "Foo"; // LimboStates.Error; Dev.Trace(name); Dev.Trace(name.HasValue); Dev.Trace(name.State); // Dev.Trace(name.Value); // Dev.Trace((string)name); } } // module Start public struct Limbo { private LimboState m_State; private T m_Value; public LimboState State{ get{ return m_State; } set{ m_State = value; m_Value = default(T); } } public T Value{ get{ if(false == this.HasValue){ throw new InvalidOperationException("Cannot obtain '" + typeof(T).FullName + "' value, because this limbo is in '" + this.State + "' state."); } return m_Value; } set{ m_Value = value; m_State = null; } } public bool HasValue{ get{ return (null == m_State); } } public override bool Equals(object obj){ if(obj != null && obj.GetType().Equals(typeof(Limbo ))){ Limbo that = (Limbo ) obj; if(this.m_State != null && that.m_State != null){ return this.m_State.Equals(that.m_State); }else if(null == this.m_State && null == that.m_State){ if(typeof(T).IsValueType){ return this.m_Value.Equals(that.m_Value); }else{ return object.Equals(this.m_Value, that.m_Value); } } } return false; } public override int GetHashCode(){ if(m_State != null){ return m_State.GetHashCode(); }else{ if(m_Value != null){ return m_Value.GetHashCode(); }else{ return 0; } } } public override string ToString(){ if(m_State != null){ return m_State.ToString(); }else{ if(m_Value != null){ return m_Value.ToString(); }else{ return string.Empty; } } } public static implicit operator Limbo(T value){ Limbo l = new Limbo(); l.Value = value; return l; } public static implicit operator Limbo(LimboState state){ Limbo l = new Limbo(); l.State = state; return l; } public static explicit operator T(Limbo l){ if(false == l.HasValue){ throw new InvalidOperationException("Cannot convert to '" + typeof(T).FullName + "', because this limbo is in '" + l.State + "' state."); } return l.Value; } } // struct Limbo public abstract class LimboState : IProvider { public abstract string Name{get;} public abstract string Description{get;} public abstract bool Equals(LimboState other); // ... public override sealed string ToString(){ return this.Name; } } // abstract class LimboState public class SqlNullState : LimboState { internal SqlNullState(){return;} public override string Name{ get{return "SqlNull";} } public override string Description{ get{return "Represents null values as in databases.";} } public override bool Equals(LimboState other){ return false; } public override int GetHashCode(){ return 0; } } // class SqlNullState public class ErrorState : LimboState { internal ErrorState(){return;} public override string Name{ get{return "Error";} } public override string Description{ get{return "Represents an error state.";} } public override bool Equals(LimboState other){ return false; } public override int GetHashCode(){ return 0; } } // class ErrorState public static class LimboStates { public static readonly LimboState SqlNull = new SqlNullState(); // ... treat null references the same? public static readonly LimboState Error = new ErrorState(); } // static class LimboStates } // namespace Gregor