C # Объект / объект - PullRequest
       33

C # Объект / объект

1 голос
/ 11 октября 2009

Является ли C # Object / object типом значения или ссылочным типом?

Я проверял, что они могут хранить ссылки, но эти ссылки нельзя использовать для изменения объектов.

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

Ответы [ 6 ]

5 голосов
/ 11 октября 2009

Изменения, которые вы вносите в 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;}
}

Измените Value объекта в Swap, и вы увидите эффекты для вашей основной программы.

5 голосов
/ 11 октября 2009

Это ссылочный тип - если вы посмотрите документацию , вы увидите, что он объявлен как класс. Все классы являются ссылочными типами.

И да, то же самое верно для System.ValueType и System.Enum - оба они также являются ссылочными типами, несмотря на имена ... хотя значения типов происходят от них.

РЕДАКТИРОВАТЬ: ваше обновление показывает, что вас действительно смущает передача параметров. См. Мои статьи о передаче параметров в C # и типах ссылок / значений .

2 голосов
/ 11 октября 2009

Обратите внимание, что

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

совпадает с:

Object obj1 = 10;

Поскольку компилятор вмешивается в 'упаковку', чтобы превратить тип значения int в ссылочный тип. И внутри вашего метода Swap вы снова занимаетесь боксом, перезаписывая эталонные параметры.

Таким образом, решение Коби и 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;
 }

Таким образом, компилятор может сгенерировать наиболее подходящий код для ссылочных типов и типов значений.

0 голосов
/ 11 октября 2009

Это потому, что тип времени выполнения obj1 и obj2 равен System.Int32 (проверьте с помощью obj1.GetType().ToString()), то есть тип значения. В вашей функции свопинга не делается ссылочная копия. Вместо этого он просто выполняет операции упаковки и распаковки, которые не влияют на реальные переменные.

0 голосов
/ 11 октября 2009

Вы должны написать код, подобный этому:

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

Цитата из MSDN:

Передача параметров (Руководство по программированию в C #)

В C # параметры можно передавать либо по значению, либо по ссылке.Передача параметров по ссылке позволяет членам функции, методам, свойствам, индексаторам, операторам и конструкторам изменять значение параметров и сохранять это изменение.Чтобы передать параметр по ссылке, используйте ключевое слово ref или out.Для простоты в примерах в этом разделе используется только ключевое слово ref.Для получения дополнительной информации о разнице между ref и out см. Ref (C # Reference), out (C # Reference) и Передача массивов с использованием ref и out (Руководство по программированию в C #).Например:

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

(c) MSDN - Передача параметров (Руководство по программированию в C #)

0 голосов
/ 11 октября 2009

, поскольку object является матерью всех объектов, это ссылочный тип

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...