2

您可以将引用传递给传递控制行为的引用类型吗?

我注意到,当您将控件传递给构造函数时,它实际上传递了对该控件的引用,然后如果您将另一个控件分配给该控件,则它不是复制值,而是实际上复制了引用本身!为什么这不能用常规变量或至少用 ref 关键字来完成?

例如...

public class Test : Form
{

Test()
{
InitializeComponent();
}
Test_Load(object sender, EventArgs e)
{
new Test2((Control)MyTextBox).ShowDialog();
}

}

public class Test2 : Form
{
Public Control x_
Test2(Control x)
{
x_=x;
InitializeComponent();
}
//use x_ somewhere in code to actually change x
}

我不明白这适用于控件,但不适用于其他变量。现在假设我将 x 作为 int ref 传递,我无法将 ref 本身传递给 x_?在控件的情况下,我什至不必使用 ref ,这让我很困惑这是如何发生的......我知道如何通过方法和父/所有者来回传递变量,所以我的问题非常具体特殊的准指针。也许我误解了传递 Control 的行为,如果是这种情况,您将如何构造一个 int 与 Control 完全一样,以便当您将一个 int 分配给一个像 Control 这样的 int 时,它会更改原始 int,就像它更改原始 Control 一样.

这行得通。发送与发送相同。

    new InputBox(((Label)sender)).ShowDialog();

    Label Send;
    public InputBox(Label send)
    {
     Send=send; 
    }

我希望它以同样的方式工作。发送现在与发送相同,但不完全相同。

    new InputBox(((string)sender)).ShowDialog();

    string Send;
    public InputBox(string send)
    {
     Send=send; 
    }

我知道如何在类等之间传递变量,但我要求特别让一个字符串的行为方式与 Label 在传递时的行为方式相同。当它被传递时,它就像一个指针一样传递,因为我可以使一个变量等于该变量的同一个实例。为什么我不能使字符串等于该字符串的同一实例?

4

2 回答 2

4

我认为您需要了解的是值类型和引用类型之间的区别

值类型

如果数据类型将数据保存在自己的内存分配中,则该数据类型是值类型。

它们包括类型

  • 所有数值数据类型
  • 布尔值、字符和日期
  • 所有结构,即使它们的成员是引用类型
  • 枚举,因为它们的基础类型始终是 SByte、Short、Integer、Long、Byte、UShort、UInteger 或 ULong

然而

参考类型

引用类型包含指向另一个保存数据的内存位置的指针。

它们包括类型

  • 细绳
  • 所有数组,即使它们的元素是值类型
  • 类类型,例如 Form
  • 代表们

ref 更远(C# 参考)

ref 关键字导致参数通过引用而不是值传递。通过引用传递的效果是方法中参数的任何更改都会反映在调用方法中的底层参数变量中。

这就解释了为什么如果您希望将值类型的更改传播到 collung 方法,则需要更改方法签名以使用 ref。

这是有关构造函数调用的示例

Control c1 = null;
Class1 cl1 = new Class1(c1); //c1 is still null after this call
Control c2 = null;
Class1 cl2 = new Class1(ref c2); //c2 is NOT null after this call

class Class1
{
    public Class1(Control c)
    {
        c = new Control();
    }

    public Class1(ref Control c)
    {
        c = new Control();
    }
}
于 2013-06-10T05:25:35.147 回答
2

我认为,.NET 中字符串的不变性会让您感到困惑。

字符串引用类型。
但它设计为不可变的。

这意味着,您不能修改System.String. 每次你做任何应该修改字符串的操作时,它只会创建一个的字符串实例。看看这个样本:

class A
{
    private string someString;

    public A(string someString)
    {
        this.someString = someString;
    }

    public string SomeString
    {
        get { return someString; }
    }

    public void DoSomething()
    {
        someString = someString + "_abc";
    }
}


var sampleString = "Hello, world!";
var a = new A(sampleString);

Console.WriteLine(a.SomeString == sampleString); // prints 'true'

a.DoSomething();

Console.WriteLine(a.SomeString == sampleString); // prints 'false'
Console.WriteLine(sampleString); // prints 'Hello, world!'
Console.WriteLine(a.SomeString); // prints 'Hello, world!_abc'

最初sampleStringA.someString相等。

但在这一行之后:someString = someString + "_abc"该字段A.someString引用了字符串的另一个实例,因为+运算符创建了一个新实例,并且赋值运算符已将该实例分配给A.someString.

System.String不能表现得像Label,因为Label是可变的。因此,Label.Text = "Foobar";不会创建标签的新实例。

升级版。如果您想要一个可变字符串,它已经出现在 FCL 中。这是StringBuilder课堂。

于 2013-06-10T06:11:38.123 回答