私有变量究竟意味着什么?

时间:2013-07-12 13:26:40

标签: c#-4.0

我有一个名为form1的表单,我还有一个名为class1的类 当我试图从class1中的form1中的文本框中获取文本时。它花了两天的时间来弄清楚获取文本的正确方法。

请参阅以下代码:

我有以下课程:

class Class1
{
                   // field to hold the Form1 object reference
    private Form1 DataEntryForm;

   // Class1 constructor
    public Class1(Form1 form)
    {
       // store the Form1 object reference
        DataEntryForm = form;    
    }


    public void gettext()
    {
         //the following doesn't work..
        string textintextbox = DataEntryForm.textBox1.text;
        //I get the following error =>  somenamespace.Form1.textBox1 is inaccessible due to its protection 


//but the following code works just fine.... why?
        textintextbox =   ((TextBox)DataEntryForm.Controls.Find("textBox1",true).FirstOrDefault()).Text;
    }
}

你可以看到我知道我必须在class1中声明对表单的引用,然后像'myform1refence.textbox1.text'那样访问文本框但是如果你看一下上面的代码就不能用作textbox1是私有的。所以我谷歌就像我被解决了这个以及我去过的每个地方,人们建议我“不应该”使textBox1公开,因为它是糟糕的编程或者其他东西,但我应该创建一个像这样的公共变量

 public partial class Form1 : Form
{
    public sometype somevariablename {get { return somePrivatevariablename; } set { somePrivatevariablename = value; }}
}

所以我认为这是我应该从class1访问我的textbox1的正确方法所以我写了以下

 public partial class Form1 : Form
{
    public TextBox _textBox1 {get { return this.textBox1; } set { this.textBox1 = value; }}
}

所以当我在class1中键入以下内容时,它可以正常工作!

展览A

 string textintextbox = DataEntryForm.textBox1.text;

所以有一天我继续编码并接受这个是我问题的最佳解决方案。然后我偶然发现了以下代码:

展览B

 string textintextbox =    ((TextBox)DataEntryForm.Controls.Find("textBox1",true).FirstOrDefault()).Text;

使用上面的代码我不需要将textbox1公开为textBox1创建公共getter和setter所有我需要做的就是创建一个form1引用。

所以我的问题是为什么展览B只能参考表格而是 展览A需要对表格的引用和被访问的变量公开工作。为什么这......我错过了什么?

3 个答案:

答案 0 :(得分:3)

Exhibit A依赖于引用该组件的公共成员。如果组件不存在,设计器生成的字段(this.textBox1)也将不存在,程序将无法编译。

图表B按名称查找组件。如果该组件不存在,程序将编译得很好,但在运行时运行时失败

编译错误通常比此上下文中的运行时错误更受欢迎,但正确的选择最终取决于您的质量要求。

答案 1 :(得分:1)

为了更好地了解幕后发生的事情,我建议您安装ILSpy。从GAC打开System.Windows.Forms,然后查看Control类。

展览B 将起作用,因为Controls类的System.Windows.Form.Control属性包含所有控件,而忽略了它们的修饰符:

public Control.ControlCollection Controls
{
    get
    {
        Control.ControlCollection controlCollection = (Control.ControlCollection)this.Properties.GetObject(Control.PropControlsCollection);
        if (controlCollection == null)
        {
            controlCollection = this.CreateControlsInstance();
            this.Properties.SetObject(Control.PropControlsCollection, controlCollection);
        }
        return controlCollection;
    }
}

CreateControlsInstance的位置:

protected virtual Control.ControlCollection CreateControlsInstance()
{
    return new Control.ControlCollection(this);
}

因此,System.Windows.Forms.Control.ControlCollection.Find方法public会在整个控件集合上搜索指定的控件名称:

public Control[] Find(string key, bool searchAllChildren)
{
    if (string.IsNullOrEmpty(key))
    {
        throw new ArgumentNullException("key", SR.GetString("FindKeyMayNotBeEmptyOrNull"));
    }
    ArrayList arrayList = this.FindInternal(key, searchAllChildren, this, new ArrayList());
    Control[] array = new Control[arrayList.Count];
    arrayList.CopyTo(array, 0);
    return array;
}

答案 2 :(得分:0)

class Class1
{
    public string getText()
    {
        return DataEntryForm.textBox1.Text;
    }
}

可能就是你想要的。 getText是公开的 - 它可以被类外的东西调用:

Class1 Thingy = new Class1();
string AString = Thingy.getText();

但会阻止您访问班级内部。这是不允许的

string AnotherString = Thingy.textBox1.Text;

这也不会:

TextBox tb = Thingy.textBox1;

但是,您可以将此功能添加到您保持文本框保密的类:

public TextBox GetMyTextBox()
{
    return textBox1;
}

你可以在课堂外进行:

string Str = Thingy.GetMyTextBox().Text;

这里的要点是实际变量对于类是私有的,而你公开的只是通过成员函数。这是封装。

我强烈建议您阅读基本的面向对象原则 - 找一个关于它的在线教程或其他东西!祝你好运。