2

您是否曾经需要通知任何使用您的代码并传递一些引用类型参数的人不要传递 null?你肯定有。而且您应该为您的代码无法使用的每个“坏”变量抛出异常。

现在,让我们假设您已经创建了这个结构:

public struct NotNullable<T> where T : class
{
    // Backing field for the value. Guaranteed to return not null.
    private T _value;
    public T Value
    {
        get
        {
            if (_value == null)
                throw new ApplicationException("Value is not initialized.");

            return _value;
        }
    }

    // Easy both-ways convertible.
    public static implicit operator T(NotNullable<T> notNullable)
    {
        return notNullable.Value;
    }
    public static implicit operator NotNullable<T>(T value)
    {
        return new NotNullable<T>(value);
    }

    // These members are overridden.
    public override string ToString()
    {
        return Value.ToString();
    }
    public override int GetHashCode()
    {
        return Value.GetHashCode();
    }
    public override bool Equals(object obj)
    {
        if (obj is NotNullable<T>)
        {
            return Value.Equals(((NotNullable<T>)obj).Value);
        }

        return Value.Equals(obj);
    }

    public NotNullable(T value)
    {
        this._value = value;
    }
}

这种结构的用法:

class Program
{
    static void Main(string[] args)
    {
        NotNullable<string> a = "Hello World!";

        Console.WriteLine(a);
        Console.WriteLine((string)a);
        Console.WriteLine((object)a);
        Console.WriteLine((NotNullable<string>)a);

        // Produces fine outputs.


        var b = default(NotNullable<string>); 
        Console.WriteLine(b); // Throws an exception of non-initialized field.
    }
}

您还可以使您的方法接收不可为空的引用类型参数:

List<Tree> treeList;

public void CreateTree(NotNullable<Tree> tree)
{
    // Assume you cannot have the list contain nulls.
    treeList.Add(tree); // No null-checks required.
}

在如此有用的与结构相反的情况下可能有什么问题Nullable<>

4

1 回答 1

3

我看不出这对投掷有什么好处ArgumentNullException。事实上,我宁愿这样做:

public void Foo(MyClass item, MyClass2 item2)
{
    if (item == null)
        throw new ArgumentNullException("item");

    if (item2 == null)
        throw new ArgumentNullException("item2");
}

这样我就可以让程序员知道哪个参数不好。我NotNullable<T>想它看起来像这样:

public void Foo(NotNullable<MyClass> item, NotNullable<MyClass> item2) { ... }

Foo((NotNullable<MyClass>)myVar1, (NotNullable<MyClass2>)myVar2);

现在我被"Value is not initialized."扔在脸上。哪一个?

于 2013-08-08T12:05:30.387 回答