基本上我希望能够在类的实例中引用变量,但我希望引用成为类变量,所以我不需要在类的内部作为参数发送它
代码:
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;
我该如何解决这个问题?我不喜欢这个解决方案
答案 0 :(得分:14)
我希望能够在类的实例中引用变量,但我希望引用成为类变量,所以我不需要在类的内部作为参数发送它/ p>
那么你将不得不忍受失望。 CLR类型系统明确禁止将变量的引用存储为类的成员。 CLR允许引用变量
但不允许在数组,字段等中存储。基本上,“在堆上”的任何东西都无法保留参考。
C#公开了第一个特性:将变量作为方法参数引用。它没有公开其他两个功能(虽然我已经编写了一个C#的实验版本,它的功能非常好。)
请注意,C#不允许您在需要堆存储ref的上下文中使用ref - 例如,ref参数是lambda的封闭外部变量。有一些罕见的情况,编译器确实允许看起来像ref的长期存储,并使用copy-in-copy-out语义来模拟ref,但最好甚至不去那里。
为什么CLR有此限制?考虑它的正确方法是有两种存储:长期和短期,通常称为“堆”和“堆栈”。但数据结构的形状无关紧要;相关的是寿命的长短。变量具有存储位置;这就是变量。如果你可以在长期存储中保留一个从短期存储分配的变量的参考,那么长期存储会保留一个生命周期较短的内容,因此在访问变量时可能会崩溃并死亡死后。
显然有很多方法可以解决这个问题。例如,CLR团队可能选择将参考资料用于短期存储是非法的,并允许在长期存储中存储ref。但那意味着你不能把refs带到局部变量或参数,你想把它放在短期存储中,因为它们的生命很短暂。
CLR团队实际选择的方式是禁止长期存储任何参考。与任何设计决策一样,这是与竞争目标进行许多权衡的结果。
答案 1 :(得分:2)
你想要做什么并不是一个好主意,我会将修改后的对象公开为类的属性,如下所示:
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");
}
}
答案 2 :(得分:1)
当然你的测试代码不会工作,因为它是一个原始类型。但你的第二个代码将起作用,因为它是一个引用类型。(甚至不需要'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);
}
}
输出: -
SUli
普利
答案 3 :(得分:0)
创建一个包含您的号码作为属性的类,并将其传递给您的逻辑。该课程将代表您的“模特”。
答案 4 :(得分:0)
您无法保存ref
参数,ref
不是参考,只是alias
。如果你有:
public void Stuff (ref int i)
{
i = 2;
}
并称之为:
int s = 1;
Stuff(ref s);
ref
表示“使我成为s的别名并将更改传播给它”。一旦离开方法的范围,该别名就消失了。很明显,Eric Lippert在他的blog上开始了一个关于这个问题的系列文章。
您应该创建一个类并在逻辑中使用它。 GUI不应该操纵值,只应该操作后端。
答案 5 :(得分:0)
这里有几件事。 首先,在您的构造函数中,您可能想要
DoSomething();
number=classnumber;
而不是
classnumber=number;
第二,尝试
myClass(ref num);
而不是
myClass(num);