使一个类的实例与另一个相等。 - 如何取消?

时间:2011-09-19 20:44:33

标签: c#

我有:

instance1 = instance2;

如何将它们彼此断开,以便改变它们不会影响另一个?

编辑:我希望他们引用相同的对象(所以我无法克隆),以后 - 不是。但是我仍然想要这个类的两个实例 - 所以我不能'空'它们。

由于

编辑:

myclass a = new myclass();
a.integer = 1;

myclass b = new myclass();
b.integer = 2;

a = b;
//All changes to one will affect the other, Which is what I want.



//<More lines of the program>



//Now I want 'a' to point to something else than 'b'. and I’m missing the code
//so that the next line will not affect 'b'.
a.integer = 1;

Text = b.integer.ToString();
//I need b.integer to still be = 2, it’s not.

使用:

class myclass
{
    public int integer;
}

编辑:

答案: @ispiro但是当你说a.integer = 1时你没有改变指针,你就是跟着指针并改变它末尾的值。 - 戴维8

我原本以为改变'a'和'a.integer'都是一样的,因为改变它们会改变指针 - 'a'或不会改变指针。但实际上:第一个没有,第二个没有。

谢谢大家。

所以在上面的例子中,如果我添加:

a = c;// where c is another instance of 'myclass'.

将'a'更改为指向“b”以外的其他位置。 但是:

a.integer = 1;

没有。

9 个答案:

答案 0 :(得分:28)

您的代码:

myclass a = new myclass();
a.integer = 1;

myclass b = new myclass();
b.integer = 2;

a = b;

//here I need code to disconnect them

a.integer = 1;

Text = b.integer.ToString();
//I need b.integer to still be = 2

enter image description here

如果您保留参考:

myclass a = new myclass();
a.integer = 1;

myclass b = new myclass();
b.integer = 2;

var c = a; //Keep the old a around
a = b;

//here I need code to disconnect them
a = c; //Restore it.

a.integer = 1;

Text = b.integer.ToString();
//It's still 2 now.

enter image description here

变量是对象的标签,而不是对象本身。在您的情况下,原始a不再具有对它的引用,因此即使它存在,也无法访问它。 (只要垃圾收集器绕过去除它,除非有其他参考,否则它将不复存在)

如果有帮助,请以这种方式考虑,当您说a = ba = new myclass()时,您正在移动a指向的行。当您说a.integer = 1时,.有点像跟随a指向的行,然后更改目的地。

答案 1 :(得分:8)

假设你在一张纸上写下“1600宾夕法尼亚大道”。那个地址指的是一所房子,实际上是白宫。

假设你在第二张纸上写下“1600宾夕法尼亚大道”。该地址指的是与第一张纸相同的相同的房屋。

你绝对没有办法改变这两个地址指的是同一个房子的事实。你可以改变其中一张纸来说“123 Sesame Street”,然后他们不再引用同一个房子,但这并没有改变关于 The White House 的事实,这种情况正在发生变化关于一张纸的事实。

如果你把白宫涂成蓝色,你仍然没有改变任何一张纸;现在两个都是指一个蓝屋。

您能否详细解释一下您在这里尝试做什么?你的问题很混乱。

答案 2 :(得分:3)

我想我会根据你的意见更好地理解你所说的话。

答案非常简单。

此代码:

instance1 = instance2;

除了指向同一事物的事实之外,不以任何方式链接instance1和instance2。您始终可以重新指向任一变量(包括“取消它们”)而不会影响另一个变量。将实例设置为null不会更改对象,只会使其停止指向内存中的对象。

从本质上讲,问题的前提是不准确的。这里没有问题需要解决。

需要理解的要点:变量instance1和instance2只存储一个位置    内存中的对象,而不是实际的对象。如果您想操纵实际对象,则可以在该对象上使用方法或属性,例如:

instance1.ChangeColor; // call the ChangeColor method on the object pointed to by instance1.

更新:

假设a和b是索引卡片,其中包含可以容纳号码的邮箱地址。以下是您的代码正在进行的播放

//create a mailbox (call it X)  and write the address on index card A
myclass a = new myclass();  

//put the number 1 in the mailbox at the address written on index card A (currently x)
a.integer = 1;   //mailbox x now contains 1

//create ANOTHER mailbox (call it Y) and write the address on index card B
myclass b = new myclass(); 

//put the number 2 in the mailbox at the address written on index card B (currently Y) 
b.integer = 2;  //mailbox y now contains 2

// change the address on index card A to the address from card B (currently Y)
a = b;  //both cards now have the address of mailbox Y (which contains 2) written on them. 

// if you want a to go back to having the address of mailbox X, you are
// out of luck because you don't have it written down on any of your cards anymore.

//put the number 1 in the mailbox at the address pointed to on Card A (Currently Y)
a.integer = 1;  //mailbox Y now contains 1

//Set text to the number from the mailbox at the address on card B (currently Y)
Text = b.integer.ToString();  

答案 3 :(得分:1)

为相关类编写一个复制构造函数,并将其中一个引用指向通过复制构造函数创建的新实例。

答案 4 :(得分:1)

MyClass instance1 = new MyClass();
MyClass instance2 = new MyClass();

instance1 = instance2;

instance1 = null; //does not affect instance2.

答案 5 :(得分:0)

目前还不清楚你想做什么。显然,如果设置instance1 = null,则引用将不相同。您是在考虑如何制作深层副本吗?

您可能希望查看ICloneable界面。您必须编写将一个实例的属性复制到另一个实例的代码。

或者,您可以重载=运算符。或者创建一个可以调用的构造函数:

MyClass instance2 = new MyClass(instance1);

答案 6 :(得分:0)

您需要一种克隆实例的方法(创建实例的副本)。

例如,在您的班级中:

public MyClass(MyClass copy)
{
    // ...copy all attributes, be careful with reference variables
}

然后您可以执行以下操作:

instance1 = new MyClass(instance2);

它们都具有完全相同的属性和属性(如果您正确实现了复制构造函数),但修改一个不会影响另一个。

答案 7 :(得分:0)

您的类可以是结构而不是使它成为值类型吗?

public void Main()
{
    MyObj a = new MyObj{ integer= 1};
    MyObj b = a;

    Console.WriteLine(a.integer); //1
    Console.WriteLine(b.integer);//1

    b.integeter = 42;

    Console.WriteLine(a.integer);//1
    Console.WriteLine(b.integer);//42
}

public struct MyObj
{
    public int integer{get; set;}
}

答案 8 :(得分:0)

我建议将类类型的字段和变量视为保存“实例ID”是最有帮助的。有些人认为它们是指针,但这是一个实现细节。要实现的基本要点是,如果Foo是类类型Bar的变量,则语句“Foo.Boz()”不会指示编译器以任何方式改变Foo;它指示编译器查找存储在Foo中的实例id引用的对象(该对象必须是Bar类型),并在该对象上运行Boz方法。实例id本身可以完成的操作非常少,而不是由此引用的对象:

  1. 可以将实例ID从一个变量或字段复制到另一个变量或字段。
  2. 实例ID可以通过值传递给方法或属性
  3. 可以通过引用方法或属性来传递实例ID
  4. 可以将实例ID与另一个进行比较(不需要查看id引用的对象 - 只是id本身)

如果Biff和Baff是相同的实例id,那么对Biff引用的对象所做的操作将影响Baff引用的对象,因为它们是同一个对象(但这样的动作实际上不会影响Biff和Baff本身,它仍将保持与以前相同的实例ID)。如果有人想要Biff引用一个类似于Baff引用的对象,但有一些区别,那么必须创建一个类似于Biff和Baff所引用的对象的新对象,存入Biff的id新对象,然后修改该对象,使其与Baff指向的方式不同。

顺便说一下,除了支持类类型之外,.net还支持值类型(例如整数,如Integer或Double,以及结构)。与类类型不同,值类型的变量和字段是不相交的;改变一个不会影响任何其他。在许多情况下,值类型可以更容易地隔离数据依赖性。然而,重要的是要注意,尽管能够在不影响任何其他值的情况下对一个值类型变量或字段进行更改是有用的,但在更改值类型实体的一部分时(例如,结构),请注意,在某些情况下,.net将默默地制作值类型实体的副本,然后对副本进行操作。