C# 公共方法中的公共对象在同一类中的另一个公共方法中不可见
我是一个努力学习和理解这种新的C#语言和OO风格的新手,我的大脑不如20年前那么敏锐。 这里我们有一个访问(.accdb)的简单数据库连接 我正在实例化一个helper类,它包含两个方法,即makeconn和readfrondb方法,如下所示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();
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)可能是个好主意。我认为.NetOleDbConnection
类正是这样做的same@GianPaolo(和其他人)会像我的助手一样自动生成im