C# 公共方法中的公共对象在同一类中的另一个公共方法中不可见

C# 公共方法中的公共对象在同一类中的另一个公共方法中不可见,c#,scope,visibility,public,C#,Scope,Visibility,Public,我是一个努力学习和理解这种新的C#语言和OO风格的新手,我的大脑不如20年前那么敏锐。 这里我们有一个访问(.accdb)的简单数据库连接 我正在实例化一个helper类,它包含两个方法,即makeconn和readfrondb方法,如下所示 public void Form1_Load(object sender, EventArgs e) { Clshelper chelp = new Clshelper(); chelp.makeconn();

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

public void Form1_Load(object sender, EventArgs e)  {

        Clshelper chelp = new Clshelper();

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

    }
这是下面创建的helper类,因为我希望在单独的方法中保留连接部分和任何类型的数据操作。 但是,除非在方法makeconn中创建连接对象con1的行抛出异常,因为con1是空对象,如果我按照下面的方式编码它

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();
      (...)
      }
但是,如果我将makeconn中创建con1连接对象的行放在readfromdb的顶部,并且只运行readfromdb,那么一切都正常。 那么为什么readfromdb方法不能“看到”我在makeconn方法中创建的con1对象呢?我认为一个类中的任何变量对同一个类中的所有方法都是可见的

线路

OleDbConnection con1 = // ...
实际上,在
makeconn
函数的范围内创建一个全新的变量。当您有另一个名为
con1
的类范围变量时,它们是分离的变量,因此将值分配给一个(函数范围)变量不会将值分配给另一个(类范围)变量

修复相当容易。与其声明新变量,不如使用您在类中已声明的变量:

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

有趣的旁注。如果函数范围变量与类范围实例变量的名称相同,则可以使用
this
关键字访问类范围变量:

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)
    }
}
线路

OleDbConnection con1 = // ...
实际上,在
makeconn
函数的范围内创建一个全新的变量。当您有另一个名为
con1
的类范围变量时,它们是分离的变量,因此将值分配给一个(函数范围)变量不会将值分配给另一个(类范围)变量

修复相当容易。与其声明新变量,不如使用您在类中已声明的变量:

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

有趣的旁注。如果函数范围变量与类范围实例变量的名称相同,则可以使用
this
关键字访问类范围变量:

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)
    }
}

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

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

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
        }
    }
}
公共类产品存储库
{
私有只读字符串_connectionString;
公共MyRepository(字符串连接字符串)
{
_connectionString=connectionString;
}
公共列表产品()
{
使用(var连接=新的OLEDB连接(_connectionString))
使用(var命令=新的OleDbCommand(“命令文本”,连接))
{
connection.Open();
//在此处执行命令并返回结果
}
}
公共产品(产品)
{
使用(var连接=新的OLEDB连接(_connectionString))
使用(var命令=新的OleDbCommand(“命令文本”,连接))
{
connection.Open();
//在这里执行命令
}
}
}

使用(此处未显示)进一步简化了它,因此您不必创建命令对象并将结果映射到强类型类。

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

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

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
        }
    }
}
公共类产品存储库
{
私有只读字符串_connectionString;
公共MyRepository(字符串连接字符串)
{
_connectionString=connectionString;
}
公共列表产品()
{
使用(var连接=新的OLEDB连接(_connectionString))
使用(var命令=新的OleDbCommand(“命令文本”,连接))
{
connection.Open();
//在此处执行命令并返回结果
}
}
公共产品(产品)
{
使用(var连接=新的OLEDB连接(_connectionString))
使用(var命令=新的OleDbCommand(“命令文本”,连接))
{
connection.Open();
//在这里执行命令
}
}
}

使用(此处未显示)将其进一步简化,因此您不必创建命令对象并将结果映射到强类型类。

只需将
OleDbConnection con1=new-OleDbConnection(…)
更改为
this.con1=new-OleDbConnection(…)使用一些命名约定来帮助识别成员变量,例如“代码> MyCON1/<代码>或 > CON1(基于使用什么约定的真正意见),但我建议使用与“局部变量/函数参数使用的“简单名称”不同的东西)您不应该在字段(类级别变量)中存储数据库连接。ADO.NET连接(如OleDbConnection)实现它们应该在using块中创建。@mason,对于
Clshelper
这样的连接助手来说,将连接存储在成员变量中(并使类本身实现IDisposable)可能是个好主意。我认为.Net
OleDbConnection
类正是这样做的same@GianPaolo(和其他人)会像我的助手一样自动生成im