如何判断泛型类型的字段是否已初始化?

时间:2013-11-06 14:46:32

标签: c# generics

我有一个定义流畅界面的类,包括Else方法,只能调用一次。我遇到的问题是如何判断它是否被调用。目前,我通过一个额外的bool字段来做这件事:

public class FluentMatcher<T1, T2, TResult>
{
    private bool _elseValueSet;
    private TResult _elseValue;

    ...

    public FluentMatcher<T1, T2, TResult> Else(TResult resultIfElseRequired)
    {
        if (_elseValueCalled)
        {
            throw new ElseAlreadyAddedException();
        }
        _elseValue = resultIfElseRequired;
        _elseValueSet = true;
        return this;
    }
}

我对此感到不舒服,所以我正在考虑这样的事情:

public class FluentMatcher<T1, T2, TResult>
{
    private Initialisable<TResult> _elseValue;

    ...

    public FluentMatcher<T1, T2, TResult> Else(TResult resultIfElseRequired)
    {
        if (_elseValue != null)
        {
            throw new ElseAlreadyAddedException();
        }
        _elseValue = new Initialisable<TResult>(resultIfElseRequired);
        return this;
    }
}

这提出了两个问题:

  1. 是否已经有办法测试该字段是否已初始化?我假设没有,因为它可能是一个结构,因此不能为空。我错过了什么吗?
  2. 我有一种感觉,我不是用我的新版本修复任何东西而且我正在玩语义。第一个版本工作正常,我觉得它很难看。在这种情况下,是否有充分的理由不使用bool?

1 个答案:

答案 0 :(得分:2)

您的Else方法应返回另一个非常相似的界面 - 的方法具有Else方法,因此您将无法再调用两次。

以下是我正在处理的应用程序的示例。

public class AddColumn
{
    internal AddColumn()
    {

    } 

    public NamedAddColumn Named(string name)
    {
        return new NamedAddColumn(name);
    }
}

public class NamedAddColumn
{
    protected string Name {get; set;}

    internal NamedAddColumn(string name)
    {
        Name = name;
    }

    public VarcharTypedAddColumn Varchar
    {
        get
        {
            return new VarcharTypedAddColumn(Name);
        }
    }
}

这是一个用于创建数据库迁移的流畅界面。如您所见,Named方法返回一个不同的类,具有非常相似的语义含义(它们都代表一列) - 但是,此类不允许您对列“命名”两次。

这就是你使用这个界面的方式:

        db.AlterTable(tb => tb
                                .Named("Users")
                                .AddColumn(column => column
                                                         .Named("age")
                                                         .Integer
                                )
                                .AddColumn(column => column
                                                         .Named("username")
                                                         .Varchar
                                )

修改 在你的情况下,你会有这样的事情:

public class FluentMatcher<T1, T2, TResult>
{
    /*
       Methods A B C

     */

    public FluentMatcherWithElse<T1, T2, TResult> Else(TResult resultIfElseRequired)
    {
        return new FluentMatcherWithElse(resultIfElseRequired);
    }
}

public class FluentMatcherWithElse<T1, T2, TResult>
{
    internal FluentMatcherWithElse(TResult resultIfElseRequired) { ... }

    /*
       Methods A B C - but NO else method

     */
}