c#:在类中保留构造函数的ref参数

基本上我希望能够在类的实例中引用变量,但我希望引用成为类变量,所以我不需要在类的内部作为参数发送它

码:

int num = 0; myClass(num); print num; // output is 0 but i'd like it to be 10 :) class myClass { private int classNumber; myClass(ref int number) { print number; //output is 0 // id like this to be a reference to the refenrence classNumber = number; DoSomething(); } public void DoSomething() { ClassNumber = 10; } } 

为什么我问这是因为我正在使用winforms并且有一个主表单将一个类的实例发送到一个新表单,该表单应该编辑该类并将其发回…现在我使用Form.ShowDialog()来避免用户在新表单中编辑时使用主表单,然后从新表单中获取数据

 editForm edtfrm = new editForm(ref instanceOfClass); edtfrm.showDialog(); //grab the instance back instanceOfClass = edtfrm.editedClass; 

我怎么解决这个问题? 我不喜欢这个解决方案

我希望能够在类的实例中引用变量,但我希望引用成为类变量,所以我不需要在类的内部作为参数发送它

那么你将不得不忍受失望。 CLR类型系统明确禁止将变量的引用存储为类的成员。 CLR允许引用变量

  • 传递给方法作为对应于forms参数或’this’的参数
  • 存储为本地人
  • 作为方法返回值返回

但不允许存储在数组,字段等中。 基本上,任何“在堆上”的东西都无法保留参考。

C#公开了第一个特性:将变量作为方法参数引用。 它没有公开其他两个function(虽然我已经编写了一个C#的实验版本,并且它工作得非常好。)

请注意,C#不允许您在需要堆存储ref的上下文中使用ref – 例如,ref参数是lambda的封闭外部变量。 有一些罕见的情况,编译器确实允许看起来像ref的长期存储,并使用copy-in-copy-out语义来模拟ref,但最好甚至不去那里。

为什么CLR有此限制? 考虑它的正确方法是有两种存储:长期和短期,通常称为“堆”和“堆栈”。 但数据结构的形状无关紧要; 相关的是寿命的长短。 变量具有存储位置; 这就是变量。 如果你可以在长期存储中保留一个从短期存储分配的变量的参考,那么长期存储会保留一个更短的生命周期,因此在访问变量时可能会崩溃并死亡死后。

显然有很多方法可以解决这个问题。 例如,CLR团队本可以选择将参考资料用于短期存储是非法的,并允许在长期存储中存储ref。 但那意味着你不能把refs带到局部变量或参数,你想把它放在短期存储中,因为它们的生命很短暂。

CLR团队实际选择的方式是禁止长期存储任何参考。 与任何设计决策一样,这是针对竞争目标的许多权衡的结果。

你想要做的事情并不是一个好主意,我会将修改后的对象作为类的属性公开,如下所示:

 public class ClassContructorReference { static void Main(string[] args) { object var = new object(); MyClass myClass = new MyClass(var); StringBuilder mySb = myClass.Instance as StringBuilder; Console.WriteLine(mySb.ToString()); } } public class MyClass { public object Instance {get;set;} public MyClass(object var) { this.Instance = var; DoSomething(); } private void DoSomething() { this.Instance = new StringBuilder("Hello"); } } 

当然,你的测试代码不会工作,因为它是一个原始类型。但你的第二个代码将工作,因为它是一个引用类型。(甚至不需要’ref’)不需要分配实例。

 public class Second { public First f; public Second(First f) { this.f= f; } public void change() { this.f.Name = "PUli"; } } public class First { private string _name; public First() { Name = "SUli"; } public string Name { get { return _name; } set { _name = value; } } } class Program { static void Main(String[] args) { First f = new First(); Second sec = new Second(f); Console.WriteLine(f.Name); sec.change(); Console.WriteLine(f.Name); } } 

输出: –

苏力

埔里

创建一个包含您的号码作为属性的类,并将其传递给您的逻辑。 该课程将代表您的“模特”。

你不能保存ref参数, ref不是引用,它只是一个alias 。 如果你有:

 public void Stuff (ref int i) { i = 2; } 

并称之为:

 int s = 1; Stuff(ref s); 

ref意味着“使我成为s的别名并将更改传播给它”。 一旦离开方法的范围,该别名就消失了。 很明显,Eric Lippert在他的博客上开始了一个关于这个问题的系列文章 。

您应该创建一个类并在逻辑中使用它。 GUI不应该操纵值,只应该操作后端。

这里有几件事。 首先,在你的构造函数中,你可能想做

 DoSomething(); number=classnumber; 

代替

 classnumber=number; 

第二,尝试

 myClass(ref num); 

代替

 myClass(num);