public 来自 public 方法的对象在同一 class 的另一个 public 方法中不可见

public Object from public method not visible in another public method in same class

我是一个努力学习和弄清楚这种新的 C# 语言和 OO 风格的新手,我的大脑不像 20 年前那么敏锐。 这里我们有一个简单的数据库连接到 Access (.accdb) 我正在实例化一个助手 class,它包含两个方法,即 makeconn 和 readfrondb 方法,如下所示

public void Form1_Load(object sender, EventArgs e)  {

        Clshelper chelp = new Clshelper();

        chelp.makeconn(); 
        chelp.readfromdb();

    }

这是下面的助手 class - 创建是因为我想保留连接部分以及我在单独的方法中执行的任何类型的数据操作。 但是,除非在方法 makeconn 中创建连接对象 con1 的行抛出异常,因为如果我将其编码如下,则 con1 是 NULL 对象。

public class Clshelper {
    public OleDbConnection con1;
    public OleDbCommand cmd;

    public Clshelper() {
        Console.WriteLine("instantiated Cls_helper()");
    }

    public void  makeconn() {   
       OleDbConnection con1 = new OleDbConnection("Provider = Microsoft.ACE.OLEDB.12.0; Data Source = D:\DATA.accdb");
    }

    public void readfromdb() {

        con1.Open();
      (...)
      }

但是,如果我将创建 con1 连接对象的 makeconn 行放入 readfromdb 的顶部,并且只有 运行 readfromdb 一切正常。 那么为什么 readfromdb 方法不能 "see" 我在 makeconn 方法中创建的 con1 对象 - 我认为 class 中的任何变量对同一个 class 中的所有方法都是可见的??

OleDbConnection con1 = // ...

实际上是在makeconn函数的范围内创建了一个全新的变量。虽然您有另一个名为 con1 的 class 范围的变量,但它们是分开的变量,因此将值分配给一个(函数范围的)变量不会将值分配给另一个(class -scoped) 变量。

修复非常简单。与其声明一个新变量,不如使用您已经在 class:

中声明的变量
public void  makeconn() {
   // Don't declare a new variable here:
   con1 = new OleDbConnection("Provider = Microsoft.ACE.OLEDB.12.0; Data Source = D:\DATA.accdb");
}

有趣的旁注。如果你有一个与 class 作用域实例变量同名的函数作用域变量,你可以使用 this 关键字访问 class 作用域变量:

class MyClass {
    private int myVar = 1;

    private void myFunc(){
        int myVar = 2; // function-scoped myVar overrides class-scoped myVar

        int myOtherVar;

        myOtherVar = myVar; // myOtherVar = 2 (function-scoped myVar)
        myOtherVar = this.myVar; // myOtherVar = 1 (class-scoped myVar)
    }
}

您的助手 class 无法遵循有关处理连接的良好做法。最终这会导致可用连接耗尽。当这种情况发生时,很难追踪到。这就是为什么在使用 IDisposable 对象时需要小心,以确保正确处理它们。

下面是正确遵循此模式的一种方法:

public class ProductRepository
{
    private readonly string _connectionString;

    public MyRepository(string connectionString)
    {
        _connectionString = connectionString;
    }

    public List<Product> GetProducts()
    {
        using (var connection = new OleDbConnection(_connectionString))
        using (var command = new OleDbCommand("command text", connection))
        {
            connection.Open();
            //execute command and return results here
        }
    }

    public void AddProduct(Product product)
    {
        using (var connection = new OleDbConnection(_connectionString))
        using (var command = new OleDbCommand("command text", connection))
        {
            connection.Open();
            //execute command here
        }
    }
}

使用 Dapper(此处未显示)进一步简化它,因此您不必创建命令对象并映射结果 to/from 您的强类型 classes。