我想知道如何在.net中存储对象的引用。
也就是说,我想要类似下面的代码(当然,请注意,以下代码可能与实际操作方式有关):
class Test
{
private /*reference to*/ Object a;
public Test(ref int a)
{
this.a = a;
this.a = ((int)this.a) + 1;
}
public Object getA() { return this.a; }
}
/*
* ...
*/
static void Main(string[] args)
{
int a;
a=3;
Test t = new Test(ref a);
Console.WriteLine(a);
Console.WriteLine(t.getA());
Console.ReadKey();
}
产生以下输出:
4
4
理想情况下,我想在没有围绕整数编写包装类的情况下这样做。
换句话说,我想我想要.Net中的指针。
答案 0 :(得分:36)
您无法在.NET中存储对变量的引用。您可以存储对对象的引用,但不能存储对变量的引用。
原因是如果允许存储对任意变量的引用,那么您可以存储对局部变量的引用。如果可以存储对局部变量的引用,那么运行时就不能使用在短期内存池(即堆栈)上存储局部变量的优化。
现在,即使您可以这样做,您描述的操作也不是因为其他原因而不是类型安全的。你有一个(非常糟糕命名的)字段变量“a”类型为“对象变量的引用”和一个(非常严重且容易混淆的)局部变量“a”类型为“引用int变量”。即使你可以存储对变量的引用,在“引用对象变量”类型的东西中存储对int变量的引用也没有任何意义,因为这两种类型在逻辑上是不兼容的。您可以对它们执行的操作是不同的;对象变量的引用可以写入一个字符串;对int变量的引用不能。
也许我误解了,但不会将上面的整数变量装入一个可以存储为参考的对象中?
您对对象的引用与变量的引用相混淆。令人困惑的是,我们对两个不同的东西使用相同的术语。
是的,拳击将值类型(如int)转换为引用类型,如object。对于变量的引用,这绝对没有什么用处。
当您对变量进行引用时,您正在为该变量创建别名。当你说
void M(ref int y) { y = 123; }
...
int x = 0;
M(ref x);
你说“x和y是同一个变量的两个不同的名字”。
现在,如果您想要做的是代表“我已经捕获了一个变量并且我希望能够读取和写入它”的概念,那么请使用委托:
class Ref<T>
{
private Func<T> getter;
private Action<T> setter;
public Ref(Func<T> getter, Action<T> setter)
{
this.getter = getter;
this.setter = setter;
}
public T Value
{
get { return getter(); }
set { setter(value); }
}
}
...
int abc = 123;
var refabc = new Ref<int>(()=>abc, x=>{abc=x;});
... now you can pass around refabc, store it in a field, and so on
refabc.Value = 456;
Console.WriteLine(abc); // 456
Console.WriteLine(refabc.Value); // 456
有意义吗?
答案 1 :(得分:9)
C#没有类似于C ++ int& a
的引用变量的概念。有解决方法。一种是使用闭包:
class Test
{
private Func<int> get_a;
private Action<int> set_a;
public Test(Func<int> get_a, Action<int> set_a)
{
this.get_a = get_a;
this.set_a = set_a;
this.set_a(this.get_a() + 1);
}
public Object getA() { return this.get_a(); }
}
/*
* ...
*/
static void Main(string[] args)
{
int a;
a=3;
Test t = new Test(() => a, n => { a = n; });
Console.WriteLine(a);
Console.WriteLine(t.getA());
Console.ReadKey();
}
我不在VS面前,所以请原谅任何令人尴尬的失礼。