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

C# 如何判断泛型类型的字段是否已初始化?,c#,generics,C#,Generics,我有一个类定义了一个流畅的接口,包括一个Else方法,该方法只能调用一次。因此,我的问题是,如何判断它是否被调用。目前,我正在通过一个额外的布尔字段执行此操作: public class FluentMatcher<T1, T2, TResult> { private bool _elseValueSet; private TResult _elseValue; ... public FluentMatcher<T1, T2, TResult

我有一个类定义了一个流畅的接口,包括一个
Else
方法,该方法只能调用一次。因此,我的问题是,如何判断它是否被调用。目前,我正在通过一个额外的布尔字段执行此操作:

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;
    }
}
公共类FluentMatcher
{
私有布尔(elseValueSet),;
私人信托基金;
...
public FluentMatcher Else(需要TResult resultIfElseRequired)
{
如果(_elseValueCalled)
{
抛出新的ElsealReadyAddedeException();
}
_elseValue=resultIfElseRequired;
_elseValueSet=true;
归还这个;
}
}
但我对此感到不舒服,因此我正在考虑:

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;
    }
}
公共类FluentMatcher
{
私人首字母缩写_elseValue;
...
public FluentMatcher Else(需要TResult resultIfElseRequired)
{
如果(_elseValue!=null)
{
抛出新的ElsealReadyAddedeException();
}
_elseValue=新的初始值(resultIfElseRequired);
归还这个;
}
}
这提出了两个问题:

  • 是否已经有方法测试字段是否已初始化?我假设不是,因为它可能是一个结构,因此不能为null。我错过什么了吗
  • 我有一种感觉,我并没有真的用我的新版本修复任何东西,我在玩语义。第一个版本很好用,我只是觉得很难看。在这种情况下,是否有充分的理由不使用bool

  • 您的
    Else
    方法应该返回另一个非常类似的接口-一个没有not
    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
    
         */
    }
    
    公共类FluentMatcher
    {
    /*
    方法A、B、C
    */
    public FluentMatcherWithElse(需要TResult resultIfElseRequired)
    {
    返回新的FluentMatcherWithElse(resultIfElseRequired);
    }
    }
    公共类FluentMatcherWither
    {
    内部FluentMatcherWithElse(需要TResult resultIfElseRequired){…}
    /*
    方法A、B、C,但不包括其他方法
    */
    }
    
    我的2美分:我喜欢你原来的解决方案。“它清晰、简洁,而且很有效。”罗伊迪库斯感谢您的反馈。我认为dcastro提出了一个很好的解决方案(防止通过使用接口调用其他方法),所以我就这样做。顺便说一句,这种技术对于指定调用方法的顺序也很有用。这是一个非常好的想法。我会用的,谢谢。