你能参考一下吗?

时间:2013-06-10 05:19:03

标签: c# ref

您是否可以将引用传递给传递Control行为的引用类型?

我注意到当你将控件传递给构造函数时,它实际上传递了对该控件的引用,然后如果你为该控件分配另一个控件,它不会复制值,而是实际复制引用本身!为什么不能使用常规变量或至少使用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,这让我感到困惑的是如何发生这种情况...我知道如何通过方法和父/所有者来回传递变量所以我的问题非常具体到这个特别是准指针。也许我误解了如何传递一个控件的行为,如果是这样的话,你将如何构造一个完全像控件这样的int,这样当你像控件一样将int赋给int时,就像改变原始控件一样改变了原来的int。

这很有效。发送是selfsame发送。

    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传递时的行为方式相同。当它被传递时,它就像一个指针一样传递,因为我可以使变量等于该变量的同一个实例。为什么我不能使字符串等于该字符串的相同实例?

2 个答案:

答案 0 :(得分:4)

我认为您需要了解的是Value Types and Reference Types

之间的区别
  

价值类型

     

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

它们包括

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

,而

  

参考类型

     

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

它们包括

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

ref (C# Reference)

更远
  

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

这解释了为什么你需要更改方法signiture以使用ref,如果你希望对collung方法的值类型propogate进行更改。

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

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

答案 1 :(得分:2)

我认为,.NET中字符串的不变性是一件令你困惑的事情。

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

这意味着您无法修改 System.String的实例。每次进行任何操作时,都应该修改字符串,它只会创建一个 new 字符串实例。看看这个样本:

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";不会创建新的标签实例。

<强> UPD 即可。 如果你想要一个可变的字符串,它已经存在于FCL中。这是StringBuilder类。