none
如何写一个struct能像Nullable那样被null赋值? RRS feed

  • 问题

  • Nullable是个struct,它可以这样写:

    Nullable<X> x;
    x=null;
    我想做一个类似Nullable的struct:FusionType<X,Y>,类似object,但只能保存A和B类型。

    FusionType<A,B> x = new A;
    x = new B;
    x = null;
    if (x) 
      if (x.isX) 
        x.x.foo(); 
    else 
      x.y.foo()


    基本上都实现了,除了:
    x = null;
    有办法实现吗?因为Nullable做到了。

    还有就是,没有好办法特化,例如:我经常使用FusionType<A,B>,A、B类都有方法foo
    那我希望:

    FusionType<A,B> x;
    x.foo();相当于:
    if (x.isX) x.x.foo();
    else if (x.isY) x.y.foo();
    else throw new NullPointException();
    ....
    这个就不知如何做了。

    如果struct能继承,那就好办了

    struct AorB:Fusion<A,B>
    {
        void foo(){if (x!=null) x.foo() else if (y!=null)y.foo();else throw new Exception();}
    }

    可惜struct又不能继承。


    2013年1月9日 3:21

答案

  • 自定义的Struct绝对不允许使用null,即便你自己写null,那CLR会被自动转化成一个空的构造函数(是语法糖问题)。

    你可以这样做(重写=):

    struct MyStruct<AB>
        {
            private A a = default(A);
            private B b = default(B);
            public bool IsNull { getset; }
            public MyStruct()
            {
                IsNull = true;
            }
            public MyStruct(A _a, B _b)
            {
                a = _a;
                b = _b;
                IsNull = false;
            }
            public static implicit operator MyStruct<A, B>(object obj)
            {
                return obj == null ? new MyStruct<A, B>() : new MyStruct<A, B>(default(A), default(B));
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                MyStruct<intint> a = null;
            }
        }

    帮助一起改进论坛质量?提交你的意见于此。
    我的博客园
    慈善点击,点击此处
    和谐拯救危机,全集下载,净化人心

    2013年1月16日 4:46
    版主
  • 您好,
    請參考:How to make a 'struct' Nullable by definition?

     


    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/

    2013年1月9日 4:50
  • 你好!

        Nullable结构本身是这样实现的,并没有特别的地方,但是CRL本身对这个结构提供了支持,而你的类型的不到CLR的支持,所以,建议你实现为引用类型。

    [Serializable, StructLayout(LayoutKind.Sequential)]
    public struct Nullable<T> where T : struct
    {
    //这两个字段表示状态
    private Boolean hasValue = false; //假定null
    internal T value = default(T); //假定所有比特都是零
    
    public Nullable(T value)
    {
    this.value = value;
    this.hasValue = true;
    }
    
    public Boolean HasValue { get { return hasValue; } }
    
    public T Value
    {
    get
    {
    if (!hasValue)
    {
    throw new InvalidOperationException("Nullable object must have a value.");
    }
    return value;
    }
    }
    
    public T GetValueOrDefault() { return value; }
    public T GetValueOrDefault(T defaultValue)
    {
    if(!HasValue) return defaultValue;
    return value;
    }
    
    public override Boolean Equals(object other)
    {
    if(!HasValue) return (other == null);
    if(other == null) return false;
    return value.Equals(other);
    }
    
    public override int GetHashCode()
    {
    if(!HasValue) return 0;
    return value.GetHashCode();
    }
    
    public override string ToString()
    {
    if(!HasValue) return "";
    return value.ToString();
    }
    
    public static implicit operator Nullable<T>(T value)
    {
    return new Nullable<T>(value);
    }
    }


    周雪峰

    2013年1月9日 8:36
    版主

全部回复