C#对象/对象

C#对象/对象,c#,object,C#,Object,C#对象/对象是值类型还是引用类型 我检查了它们是否可以保留引用,但这些引用不能用于更改对象 using System; class MyClass { public static void Swap(Object obj1, Object obj2) { Console.WriteLine("After Swapping"); obj1 = 100; obj2 = 200; } } class MainClass {

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();
    }
}

它是一个引用类型-如果您查看,您将看到它被声明为一个类。所有类都是引用类型

是的,对于
System.ValueType
System.Enum
,情况也是如此-它们都是引用类型,尽管名称不同。。。但值类型是从它们派生的


编辑:您的更新显示您真正困惑的是参数传递。请参阅我在和上的文章。

这是一个引用类型-如果您查看,您将看到它被声明为类。所有类都是引用类型

是的,对于
System.ValueType
System.Enum
,情况也是如此-它们都是引用类型,尽管名称不同。。。但值类型是从它们派生的


编辑:您的更新显示您真正困惑的是参数传递。请参阅我关于和的文章。

因为
对象
是所有对象之母它是引用类型

因为
对象
是所有对象之母它是引用类型

您在
交换
中所做的更改仅限于此-您只在玩指针(和装箱),函数外的引用保持不变(您有4个引用)。如果更改了方法的签名,您将看到差异:

尝试交换(参考对象obj1,参考对象obj2)

同样的道理也适用于

Object obj1 = new Object ();
obj1 = 10;
顺便说一下,这并不比
对象obj1=10;

若要查看对象是否确实是引用类型,请使用具有属性的类,例如:

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

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

您在
Swap
中所做的更改仅限于此-您只玩指针(和装箱),函数外的引用保持不变(您有4个引用)。如果更改了方法的签名,您将看到差异:

尝试交换(参考对象obj1,参考对象obj2)

同样的道理也适用于

Object obj1 = new Object ();
obj1 = 10;
顺便说一下,这并不比
对象obj1=10;

若要查看对象是否确实是引用类型,请使用具有属性的类,例如:

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

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

您应该这样编写代码:

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();
    }
}
您可以在中阅读有关关键字“ref”的更多信息

引用MSDN:

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

在C#中,参数可以通过 通过值或引用。传递 通过引用启用参数 函数成员、方法、属性, 索引器、运算符和构造函数 更改参数值的步骤 让这种变化持续下去。通过 通过引用创建参数时,请使用ref 或out关键字。仅为简单起见 ref关键字用于 本主题中的示例。有关更多信息 关于差异的信息 在ref和out之间,参见ref(C# 参考),输出(C#参考),以及 使用ref和out(C)传递数组# 编程指南)。例如:

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

(c) 您应该编写如下代码:

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();
    }
}
您可以在中阅读有关关键字“ref”的更多信息

引用MSDN:

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

在C#中,参数可以通过 通过值或引用。传递 通过引用启用参数 函数成员、方法、属性, 索引器、运算符和构造函数 更改参数值的步骤 让这种变化持续下去。通过 通过引用创建参数时,请使用ref 或out关键字。仅为简单起见 ref关键字用于 本主题中的示例。有关更多信息 关于差异的信息 在ref和out之间,参见ref(C# 参考),输出(C#参考),以及 使用ref和out(C)传递数组# 编程指南)。例如:

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

(c)

这是因为obj1和obj2的运行时类型是
System.Int32
(请使用
obj1.GetType().ToString()
进行检查),即值类型。交换函数中没有引用副本。相反,它只执行装箱和取消装箱操作,这对实际变量没有影响。

这是因为obj1和obj2的运行时类型是
System.Int32
(请使用
obj1.GetType().ToString()
),即值类型。交换函数中没有引用副本。相反,它只执行装箱和取消装箱操作,这对实际变量没有影响。

请注意

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

Object obj1 = 10;
因为编译器通过“装箱”将值类型
int
转换为引用类型。在Swap方法中,您再次装箱,覆盖引用参数

所以Kobi和Dreamwalker的解决方案,使用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;
 }
静态无效交换(参考T x,参考T y)
{
T z=x;x=y;y=z;
}
因此编译器可以为引用类型和值类型生成最合适的代码。

请注意

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

Object obj1 = 10;
因为编译器通过“装箱”将值类型
int
转换为引用类型。在Swap方法中,您再次装箱,覆盖引用参数

所以Kobi和Dreamwalker的解决方案,使用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;
 }
静态无效交换(参考T x,参考T y)
{
T z=x;x=y;y=z;
}

因此,编译器可以为引用和值类型生成最合适的代码。

请发布一些代码,证明您无法更改对象引用。请发布