Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中存储对对象的引用#_C#_.net - Fatal编程技术网

C# 在C中存储对对象的引用#

C# 在C中存储对对象的引用#,c#,.net,C#,.net,我想知道如何在.net中存储对对象的引用 也就是说,我想要下面的代码(当然,请注意,下面的代码可能与实际操作方式有很大的出入): 要生成以下输出: 4 4 理想情况下,我不想在整数周围编写包装器类 换句话说,我想我需要.Net中的指针。您不能在.Net中存储对变量的引用,句号。可以存储对对象的引用,但不能存储对变量的引用 原因是,如果允许存储对任意变量的引用,则可以存储对局部变量的引用。如果可以存储对局部变量的引用,那么运行时就不能使用将局部变量存储在短期内存池(也称为堆栈)上的优化 现在,即

我想知道如何在.net中存储对对象的引用

也就是说,我想要下面的代码(当然,请注意,下面的代码可能与实际操作方式有很大的出入):

要生成以下输出:

4
4
理想情况下,我不想在整数周围编写包装器类


换句话说,我想我需要.Net中的指针。

您不能在.Net中存储对变量的引用,句号。可以存储对对象的引用,但不能存储对变量的引用

原因是,如果允许存储对任意变量的引用,则可以存储对局部变量的引用。如果可以存储对局部变量的引用,那么运行时就不能使用将局部变量存储在短期内存池(也称为堆栈)上的优化

现在,即使您可以这样做,您描述的操作也不是类型安全的,原因不同。您有一个类型为“引用对象变量”的字段变量“a”(名称非常糟糕),还有一个类型为“引用int变量”的局部变量(名称非常糟糕且容易混淆)。即使可以存储对变量的引用,也没有任何意义将对int变量的引用存储在“reference to object variable”类型的东西中,因为这两种类型在逻辑上不兼容。您可以对其执行的操作不同;对对象变量的引用可以写入字符串;不能对整型变量进行引用


也许我有点误解,但像上面的整数这样的变量难道不会被装箱到一个对象中,然后作为引用存储吗

您将对象引用与变量引用混淆。令人困惑的是,我们使用相同的术语来描述实际上是两件不同的事情

是的,装箱将值类型(如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
class-Ref
{
私有函数getter;
私人行动制定者;
公共引用(Func getter、Action setter)
{
this.getter=getter;
this.setter=setter;
}
公共价值
{
获取{return getter();}
集合{setter(value);}
}
}
...
int abc=123;
var refabc=newref(()=>abc,x=>{abc=x;});
... 现在您可以传递refabc,将其存储在字段中,等等
refabc.Value=456;
Console.WriteLine(abc);//456
Console.WriteLine(refabc.Value);//456
有意义吗?

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();
}
类测试
{
私人Func get_a;
私人行动组;
公共测试(Func get\u a,Action set\u a)
{
this.get\u a=get\u a;
this.set_a=set_a;
this.set_a(this.get_a()+1);
}
公共对象getA(){返回这个。get_a();}
}
/*
* ...
*/
静态void Main(字符串[]参数)
{
INTA;
a=3;
测试t=新测试(()=>a,n=>{a=n;});
控制台写入线(a);
Console.WriteLine(t.getA());
Console.ReadKey();
}

我不在VS前面,所以请原谅任何令人尴尬的失礼。

也许我误解了,但像上面的整数这样的变量不会被装箱到一个对象中,然后存储为引用吗?@Maciej:为什么会涉及装箱?装箱是将值转换为对象的过程。你为什么认为这与建立封闭有任何关系?你认为这堆东西和它有什么关系?闭包局部变量首先不会存储在堆栈上,但实际上,您不必担心这些。编译器和运行时会根据数据的使用方式确定数据最有效的存储位置。各种疯狂的黑魔法一直在幕后发生;不要担心它的魔力,担心你的程序语义。@Marcelo:但是你问的是一个关于实现细节的问题,所以不参考实现细节就不可能回答这个问题。这样看:变量定义为存储位置。因此,“对变量的引用”必须是对存储位置的引用。当您将变量传递给采用“ref”参数的方法时,实际传递的是对变量的引用——存储位置的托管地址。这是一个实现细节。@Marcelo:当您提升lambda的外部变量时,我们生成的代码告诉运行时“确保与此本地变量关联的存储在堆上,而不是堆栈上”。在那里,我们没有生成任何代码来获取本地服务器的托管地址。这里有两个概念:(1)生成代码以获取存储位置的托管地址以引用变量;(2)生成代码以确保特定存储位于长寿命堆上,而不是短命池上。这是两个完全不同的东西,彼此无关。我建议您阅读一下CLR中“值类型”和“引用类型”之间的区别。在.NET中有指针,但您不敢使用它们LOL@JohnSaunders[c语言]和[c语言]有什么区别?它们不是同义词吗?我不明白it@Pascal:我添加了这个标记,以表示像这样的问题实际上是关于C#编程语言的,而不是大多数标记为C#的问题。大多数其他问题都是关于其他问题的,但提问者恰好使用了C
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();
}