在单个代码行 C# 中分配多个变量
Posted
技术标签:
【中文标题】在单个代码行 C# 中分配多个变量【英文标题】:Assigning many variables in a single code line C# 【发布时间】:2013-02-15 03:16:26 【问题描述】:我不确定我想在 C# 中执行的操作称为什么,但我知道它可以在其他语言中完成。
假设我有三个变量并将它们设置为相同的值:
MyObject Ob1 = new MyObject(ID:1);
MyObject Ob2 = Ob1;
MyObject Ob3 = Ob1;
(假设这些变量不在同一个上下文中,我不能用它们代替一个,我也不知道它们是否存在。它们可以是一个、两个或数百个代表同一个对象...)
我知道我通过Ob3
对对象所做的更改实际上会更改Ob1
和Ob2
中的对象(当然,它们都代表具有ID:1 的同一个对象)。
但是如果我给Ob3
赋值,使用Ob3 = new MyObject(ID:2)
,这不会改变Ob1
和Ob2
的值,因为它们将继续表示ID:1 的对象。
// What happens:
Ob3 = new MyObject(ID:2);
// Ob3 is no longer the same as Ob1 and Ob2, wich are still the ID:1 object.
我想要做的是一次分配所有三个变量,就像当我写一些对应的代码到Ob3 = new MyObject(ID:2);
时,所有其他变量都代表ID:2的对象,而不是ID:1了。
//What I want:
Ob3 = new MyObject(ID:2); //using the suited operators I don't know
//And Ob1 and Ob2 become the ID:2 object as well.
我知道可以在 C++ 中使用指针来完成(显然在声明和赋值方面做了一些更改),但我不想用非托管语言管理事物。那么在 C# 中是否有类似的方法来执行“向后”分配?
【问题讨论】:
如果你要在任何地方都一样对待,那么拥有 3 个有什么意义呢?只需在所有使用 Ob2 和 Ob3 的地方使用 Ob1,您就会实现您的要求 ^ 这个。我知道您来自哪里,但变量只是对位置的引用,当您更改引用的属性时,您正在更改相同的位置。当您通过更改变量本身来更改实际位置时,它显然会改变它指向的位置。 Stan,这些变量不在同一个上下文中。 我认为没有办法做到这一点。您基本上有三个“令牌”(Ob1、Ob2 和 Ob3),它们恰好指向内存中的同一个 MtObject。如果您将新的 MyObject 分配给这些标记之一,则该标记指向内存中的新 MyObject。我很好奇你为什么要故意让三个单独的标记指向同一个东西。您真正想做的只是说“Ob1.ID = 2”吗?由于 Ob1、Ob2 和 Ob3 都指向同一个东西,那么内存中的那个 MyObject 会改变它的 ID,因此这三个会反映这一点。 我有无限数量的对象,其中包含无限数量的子对象作为成员。而且我有不定数量的 ReferencerObjects 应该存储不定数量的这些子对象。我想重新创建其中一个子对象并在所有 ReferencerObjects 中自动复制该更改。 【参考方案1】:你可以这样做:
MyObject Ob1 = new MyObject(ID:1), Ob2 = Ob1, Ob3 = Ob1;
并且所有 3 都将指向同一个对象。但是,如果你说
Ob3 = new MyObject(ID:2);
Ob1 和 Ob2 仍将指向同一个 MyObject,而 Ob3 将指向一个新的 MyObject。那是因为它们是引用类型,所以存储在 Ob1 中的值基本上是指向对象本身的指针。您想要的是所有 3 件事都指向同一件事。如果 MyObject 是可更新的,你可以这样说
Ob3.Reset(ID:2);
如果没有,你可以试试这个,但它很傻。这会让你做你想做的事情,但最好考虑一下你正在做的事情是否真的是你想做的事情。
Tuple<MyObject> Ob1 = new Tuple<MyObject>(new MyObject(ID:1)), Ob2 = Ob1, Ob3 = Ob1;
Ob3.Item1 = new MyObject(ID:2);
编辑:我想说明我认为这通常不是一件好事,它有点像黑客。可能在少数情况下它很有用,但是将变量保存在元组中通常不是什么事情。
【讨论】:
【参考方案2】:你可以这样做:
MyObject Obj1, Obj2, Obj3 = new MyObject(ID:1);
Obj1 = Obj2 = Obj3 = new MyObject(ID:2);
【讨论】:
【参考方案3】:MyObject obj1 //This create a reference variable on the stack
obj1 = new MyObject(ID:1) //This create a new object of type MyOjbect on the heap and then assigns the memory location of this new object to obj1.
MyObject obj2 //This creates a reference variable on the stack, pointing at nothing
obj2 = obj1 //This assigns the memory location of the object (already created) on the heap to the reference variable on the stack
obj3 也是一样。
你想做的事情是不可能的,你需要明确地告诉引用变量 obj1 和 obj2 指向这里创建的对象:
Ob3 = new MyObject(ID:2);
因为 obj1 不是对象,obj2 不是对象,obj3 不是对象。它是对对象内存位置的引用。因此,如果您告诉 obj3 在堆上创建一个新实例(创建一个 MyObject 类型的新对象),那绝对与 obj1 或 obj2 指向的位置无关
这是一张有助于理解的图片
引用变量保存对象在堆上的内存位置的十六进制数。因此,当您将一个引用变量分配给另一个引用变量时,您实际上只是将一个十六进制数字从一个复制到另一个,而这个十六进制数字表示对象所在的位置
【讨论】:
@Daniel 详细说明。引用变量与指针的想法相同,除了它仅用于对象(种类)。在 C++ 中,您不直接使用对象,而是使用指向对象的指针 - 非常类似于引用 在 C++ 中我可以使用 (*Pointer) = value;因此,所有指向该对象的指针都将指向该新值。 (这正是我想要做的,但在 C# 托管语言中);*Pointer
是 c++ 表示“无论我指向什么”。如果你 cout &Pointer
它将打印出对象所在的十六进制内存位置。您没有直接使用对象
我明白了。我理解指针,我只是想知道 C# 中是否有类似的“无论我指向什么”。
@Daniel 啊,它是自动的,你实际上必须使用另一个函数才能从 ref 变量中提取十六进制数以上是关于在单个代码行 C# 中分配多个变量的主要内容,如果未能解决你的问题,请参考以下文章