2009-10-11 50 views
1

是C#Object/object值类型或引用类型?C#对象/对象

我检查了他们可以保留引用,但是这个引用不能用来改变对象。

using System; 

class MyClass 
{ 
    public static void Swap(Object obj1, Object obj2) 
    { 
     Console.WriteLine("After Swapping"); 
     obj1 = 100; 
     obj2 = 200; 
    } 
} 

class MainClass 
{ 
    static void Main(string[] args) 
    { 
     Object obj1 = new Object(); 
     obj1 = 10; 

     Object obj2 = new Object(); 
     obj2 = 20; 

     Console.WriteLine(obj1.ToString()); 
     Console.WriteLine(obj2.ToString()); 

     MyClass.Swap(obj1, obj2); 

     Console.WriteLine(obj1.ToString()); 
     Console.WriteLine(obj2.ToString()); 

     Console.ReadLine(); 
    } 
} 
+0

请张贴一些代码,证明您不能更改对象引用。 – Kobi 2009-10-11 08:27:31

回答

5

更改您在Swap使仅限于那里 - 你只使用指针(和拳击)打,在函数外引用保持不变(你有4个参考)。如果您更改了方法的签名,则会看到差异:

尝试Swap(ref Object obj1, ref Object obj2)

也是一样

Object obj1 = new Object(); 
obj1 = 10; 

这并不比Object obj1 = 10;更好,通过

要查看对象实际上是一个引用类型,使用一类具有的属性,例如方式:

class Foo { 
    public int Value {get; set;} 
} 

更改Swap中对象的Value,您将看到对主程序的影响。

4

这是一个引用类型 - 如果你看一下documentation,你会看到它的声明为类。所有的类都是引用类型。

是的,System.ValueTypeSystem.Enum也是如此 - 它们都是引用类型,尽管名称...值类型从它们派生。

编辑:您的更新显示,你真正困惑的是参数传递。请参阅我的文章parameter passing in C#reference/value types

+0

plz查看更新。 – anonymous 2009-10-11 08:32:52

+0

我从来不知道System.ValueType本身就是一个引用类型...我总是认为它是一个值类型。它看起来像是一个引用类型,因此可以重写Equals()和GetHashCode()来比较内容。 – overstood 2009-10-11 10:33:29

+1

更多的是,作为一个值类型本身,没有任何东西可以从它派生出来...... – 2009-10-11 11:22:01

0

你应该写这样的代码:

using System; 

class MyClass 
{ 
    public static void Swap(ref Object obj1, ref Object obj2) // Use keyword 'ref' 
    { 
     Console.WriteLine("After Swapping"); 
     obj1 = 100; 
     obj2 = 200; 
    } 
} 

class MainClass 
{ 
    static void Main(string[] args) 
    { 
     Object obj1 = new Object(); 
     obj1 = 10; 

     Object obj2 = new Object(); 
     obj2 = 20; 

     Console.WriteLine(obj1.ToString()); 
     Console.WriteLine(obj2.ToString()); 

     MyClass.Swap(ref obj1, ref obj2); // Use keyword 'ref' 

     Console.WriteLine(obj1.ToString()); 
     Console.WriteLine(obj2.ToString()); 

     Console.ReadLine(); 
    } 
} 

可以在MSDN

报价从MSDN了解关键字 '裁判' 的更多信息:

传递参数(C#编程 指南)

在C#中,参数可以传递 按价值或参考。通过引用传递 参数可使 函数成员,方法,属性, 索引器,运算符和构造函数 更改参数 的值,并使该更改保持不变。要通过引用传递参数 ,请使用参考号 或out关键字。为了简单起见,本主题中的 示例中仅使用 ref关键字。有关ref和out之间的差异 的更多信息,请参阅参考资料(C# 参考),out(C#参考)和 使用ref和out传递数组(C# 编程指南)。例如:

// Passing by value 
static void Square(int x) 
{ 
    // code... 
} 
// Passing by reference 
static void Square(ref int x) 
{ 
    // code... 
} 

(c)中MSDN - Passing Parameters (C# Programming Guide)

0

这是因为OBJ1和OBJ2的运行时类型是System.Int32(带obj1.GetType().ToString()检查),即,值类型。您的交换功能没有参考副本。相反,它只是执行装箱和取消装箱操作,这些操作对实际变量没有影响。

+0

这不会为引用类型工作,不只是'int' - 做'obj1 = new Foo();'在本地更改引用在功能上。 – Kobi 2009-10-11 08:48:21

2

请注意,

Object obj1 = new Object(); 
obj1 = 10; 

相同:

Object obj1 = 10; 

由于编译器与“拳击”干预打开值型int成引用类型。而在你的Swap方法中,你再次装箱,覆盖参考参数。

所以了Kobi的和梦游者的解决方案,使用ref参数,将实际工作:

public static void Swap(ref Object obj1, ref Object obj2) // Use keyword 'ref' 

但很不理想。

更好的解决方案将是一个通用的方法:

static void Swap<T>(ref T x, ref T y) 
{ 
    T z = x; x = y; y = z; 
} 

因此,编译器可以产生参比和价值类型最合适的代码。

+0

从什么时候开始10 = 100? – RCIX 2009-10-11 09:05:24