设置后的空对象引用

时间:2016-10-18 10:29:37

标签: c# object parameters reference null

我尝试用一​​些小代码解释我的情况:

Class A
{
   private IDBTransaction trans;
   private IDBConnection conn;

   void Main()
   {
       B test = new B(trans)
       [some instruction]
       trans = conn.BeginTrans();
       test.Save();
   }
}

Class B
{
   private IDBTransaction trans;

   public B(IDBTransaction transaction)
   {
      trans = transaction;
   }

   void Save()
   {
      [some instruction that use transaction]
   }
}

当调用Save()时,变量B.trans被设置为null,因为在A传递参数时它是null。然后A.trans更改其值,调用BeginTrans()但B.trans仍然保持为null。我怎么解决?

2 个答案:

答案 0 :(得分:1)

您可以将事务保存在单独的对象中,例如

class TransactionInfo
{
    public IDbTransaction Transaction;  
    public IDbConnection conn;
}

然后以这种方式使用它

class A
{
    private static TransactionInfo info = new TransactionInfo();        

    static void Main()
    {
        B test = new B(info);
        //[some instruction]
        info.Transaction = info.conn.BeginTransaction();
        test.Save();
    }
}

class B
{
    private TransactionInfo _info;

    public B(TransactionInfo info)
    {
        _info = info;
    }

    public void Save()
    {
        //[some instruction that use transaction]
        _info.Transaction;
    }
}

您可以延迟您想要获得交易的时刻

public class ValueSource<T>
{
    private Func<T> _acessor;
    public ValueSource(Func<T> acessor)
    {
        _acessor = acessor;
    }

    public T Value
    {
        get 
        { 
            try 
            {
                return _acessor();
            }
            catch
            {
                return default(T);
            }
        }
    }
}

然后将上述任何解决方案传递给构造函数。延迟的例子(用于保持在单独的类示例中是相同的)

class A
{
    private static IDbTransaction trans;
    private static IDbConnection conn;

   static void Main()
   {
        B test = new B(new ValueSource<IDbTransaction>(()=>trans));
        //[some instruction]
        trans = conn.BeginTransaction();        
        test.Save();
    }
}

class B
{
    private ValueSource<IDbTransaction> trans;

    public B(ValueSource<IDbTransaction> transactionSource)
   {
        trans = transactionSource;
    }

   public void Save()
   {
      //[some instruction that use transaction]
      trans.Value;
   }
}

上述所有示例仅适用于您因某种原因希望将事务引用保留在B类中的情况。如果没有必要,我建议(如问题评论中所建议的那样)将事务作为Save方法参数传递。

class A
{
    private static  IDbTransaction Transaction;
    private static  IDbConnection conn;

    static void Main()
    {
        B test = new B();
        //[some instruction]
        Transaction = conn.BeginTransaction();
        test.Save(Transaction);
    }
}

class B
{
    public B()
    {       
    }

    public void Save(IDbTransaction transaction)
    {
        //[some instruction that use transaction]
        transaction
    }
}

请记住:如果没有必要,不要在数据结构中存储任何内容。没有状态的类包含较少的错误,并且更容易测试。

答案 1 :(得分:1)

我会将trans作为参数传递给Save()方法而不是构造函数,对于具有更长生命周期的对象持有事务引用是没有用的。 (至少比交易时间长)这样您可以在不同/多个交易中使用Save(trans)方法。

void Main()
{
    B test = new B();
    [some instruction]
    trans = conn.BeginTrans();
    test.Save(trans);
}
 Class B
 {
    void Save(IDBTransaction transaction)
    {

    }
}