Является ли объект ссылочным типом или типом значения?

У меня все еще есть сомнения насчет object. Это основной базовый класс всего, любого класса. Но это ссылочный тип или тип значения. Или как какой из этих актов это? Мне нужно это уточнить. Мне трудно это понять.

     object obj1 = "OldString";
     object obj2 = obj1;
     obj1 = "NewString";
     MessageBox.Show(obj1 + "   " + obj2);
     //Output is  "NewString   OldString" 

В этом случае он действует как тип значения. Если объект был ссылочным типом, то почему значение obj2 по-прежнему «OldString»

   class SampleClass
    {
        public string Text { get; set; }
    }

    SampleClass Sample1 = new SampleClass();
    Sample1.Text="OldText";         

    object refer1 = Sample1;
    object refer2 = refer1;

    Sample1.Text = "NewText";

    MessageBox.Show((refer1 as SampleClass).Text +  (refer2 as SampleClass).Text);
    //OutPut is "NewText   NewText"   

В этом случае он действует как ссылочный тип

Мы можем сделать вывод, что тип object — это то, что вы упаковываете внутри него. Это может быть как ссылочный тип, так и тип значения. Это о том, что вы коробите внутри. Я прав?


person UfukSURMEN    schedule 16.07.2013    source источник


Ответы (4)


Это ссылочный тип

Выполнение примера со строкой не очень понятно, потому что строка также является ссылочным типом (как и SampleClass, очевидно); ваш пример содержит ноль "бокс".

если объект является ссылочным типом, то почему значение obj2 по-прежнему "OldString"

Почему бы и нет? Когда вы создаете новую строку, старые ссылки не изменяются так, чтобы они указывали на новую строку. Рассмотреть возможность:

 object obj1 = "OldString";
 // create a new string; assign obj1 the reference to that new string "OldString"

object obj2 = obj1;
 // copy the reference from obj1 and assign into obj2; obj2 now refers to
 // the same string instance

 obj1 = "NewString";
 // create a new string and assign that new reference to obj1; note we haven't
 // changed obj2 - that still points to the original string, "OldString"
person Marc Gravell    schedule 16.07.2013
comment
использование строки в качестве примера - очень плохая идея. строка является ссылкой, но она также неизменяема. Когда вы создаете новый, он сначала просматривает пул строк, чтобы увидеть, существует ли уже подобная строка. string — это особый случай, не используйте его для объяснения концепций, связанных со ссылками и типами значений. - person Markus; 14.07.2017
comment
Когда вы создаете новый, он сначала просматривает пул строк, чтобы увидеть, существует ли уже подобная строка. - это... не совсем так. Он будет проверять в некоторых случаях, но не в общем случае. Что касается того, почему я вообще использовал строку: потому что вопрос конкретно касался строки. - person Marc Gravell; 14.07.2017
comment
Хорошо, я понял, строка - это ссылочный тип. Но то же самое и с типом int. Присвоение нового целочисленного значения первой переменной не изменяет значение другой. Это сбивает с толку. - person Sinan ILYAS; 26.02.2020
comment
@SinanILYAS, присваивающий новую вещь переменной никогда ничего не меняет в старой вещи; Я не вижу путаницы - вопрос здесь только в том, является ли вещь неизменной, т.е. можем ли мы изменить свойства части вещи, не заменяя всю вещь целиком? В случае int и string ответ - нет, мы не можем - они неизменяемы. - person Marc Gravell; 26.02.2020

Когда вы делаете

obj1 = "NewString";

на самом деле он содержит новую ссылку на другую ячейку памяти, а не на ту, которую вы указали для obj2 раньше. Когда вы измените содержимое местоположения obj1, вы получите такое же изменение в obj2.

Попробуйте изменить содержимое obj1 с помощью

fixed(char* c = obj1 as string)
{
    c = '0';
}

Обе ваши строки теперь будут "0ldString".

Это потому, что объекты являются ссылочными типами.

person pascalhein    schedule 16.07.2013

Переменная object всегда является ссылочным типом.

object может "ссылаться" на тип значения силой бокса. Поле представляет собой оболочку ссылочного типа вокруг значения, на которое ссылается переменная object.

int x = 10;     // a value-type
object o = x;

Переменная o является ссылкой на поле, содержащее значение x, но это не x:

x = 20;
MessageBox.Show( string.Format( "x:{0} o:{1}", x, o ) );

Это может быть более наглядно с изменяемым типом значения:

struct SampleClass
{
    public string Text { get; set };
    public override string ToString() { return Text; }
}

var x = new SampleClass{ Text = "Hello" };
object o = x;
x.Text = "World";
MessageBox.Show( string.Format( "{0} {1}", x, o ) );

o — это ссылка на x в рамке, поэтому изменение значения x не влияет на o.

Изменение SampleClass на класс вместо структуры (тип ссылки вместо типа значения) изменит поведение: строка object o = x; заставит o ссылаться на то же самое, что и x, а изменение текста x также изменит текст o.

person SteveLove    schedule 16.07.2013
comment
очень хорошо объяснил Стив. Итак, в случае int создается оболочка. Однако в случае структуры она напрямую преобразуется в ref-тип. Я прав? Мне просто интересно, почему .net framework не использует одну и ту же технику для обоих? Я имею в виду, почему int не может быть преобразован в ref-тип или почему структура не может быть назначена оберткой на нем? - person Ashif Nataliya; 24.06.2015

Объектная переменная всегда имеет ссылочный тип. Классы и строки являются ссылочными типами. Struct и enum являются типами значений. Я собрал большой пример из разных ресурсов.

// PrintedPage is a value type
//this is a struct
struct PrintedPage
{
    public string Text;
}

// WebPage is a reference type
class WebPage
{
    public string Text;
}

struct SampleClass
{
    public string Text { get; set; }
    public override string ToString() { return Text; }
}

void Main()
{
        // First look at value type behaviour
        PrintedPage originalPrintedPage = new PrintedPage();
        originalPrintedPage.Text = "Original printed text";

        // Copy all the information
        PrintedPage copyOfPrintedPage = originalPrintedPage;

        // Change the new copy
        copyOfPrintedPage.Text = "Changed printed text";

        // Write out the contents of the original page.
        // Output=Original printed text
        Console.WriteLine ("originalPrintedPage={0}",
                           originalPrintedPage.Text);


       //-------------------------------------------------------------------
        // Now look at reference type behaviour
        WebPage originalWebPage = new WebPage();
        originalWebPage.Text = "Original web text";

        // Copy just the URL
        WebPage copyOfWebPage = originalWebPage;
        // Change the page via the new copy of the URL
        copyOfWebPage.Text = "Changed web text";

        // Write out the contents of the page
        // Output=Changed web text
        Console.WriteLine ("originalWebPage={0}",
                           originalWebPage.Text);

        // Now change the copied URL variable to look at
        // a different web page completely
        copyOfWebPage = new WebPage();
        copyOfWebPage.Text = "Changed web page again";

         Console.WriteLine ("originalWebPage={0}",
                           originalWebPage.Text);
        Console.WriteLine ("copyOfWebPage={0}",
                           copyOfWebPage.Text);


       //-------------------------------------------------------------------
        //string are reference type too
         object obj1 = "OriginalString"; // create a new string; assign obj1 the reference to that new string "OriginalString"
         object obj2 = obj1;// copy the reference from obj1 and assign into obj2; obj2 now refers to // the same string instance
         obj1 = "NotOriginalString";// create a new string and assign that new reference to obj1; note we haven't // changed obj2 - that still points to the original string, "OriginalString"
        /*   When you do obj1 = "NewString"; it actually holds a new reference, to another memory location, not the same location you gave to obj2 before. 
           IMP -  When you change the content of the location obj1, you will get the same change in obj2.
        */
         Console.WriteLine(obj1 + "   " + obj2);

       //-------------------------------------------------------------------
         object onj11 = 2; 
         object obj12 = onj11;
         onj11 = 3; //you assigned boj11 to a new reference but obj12 reference did not change
         Console.WriteLine(onj11 + "   " + obj12);

       //-------------------------------------------------------------------     
         /*look below - it's possible for object to "reference" a value-type by the power of boxing. The box is a reference-type wrapper around a value, to which the object variable refers.*/
         int i = 2; //int is value type
         object j = i; //variable j is a reference to a box containing the value of i- but it's not i
         i = 3;  
         Console.WriteLine(i + "   " + j);       

       //-------------------------------------------------------------------
        var x = new SampleClass{ Text = "Hello" };
        object o = x;
        x.Text = "World";
        Console.WriteLine(x.Text + "   " + o);

       //-------------------------------------------------------------------
        SampleClass x1 = new SampleClass{ Text = "Hello" }; //sample class is of type struct which is value type; it is was of type class then the data would be copied over and result would be World World
        SampleClass o1 = x1;
        o1.Text = "World";
        Console.WriteLine(x + "   " + o);
    }

Ссылки – http://jonskeet.uk/csharp/references.html

person user3311298    schedule 25.11.2016
comment
Спасибо за ваше объяснение. это действительно поучительно - person UfukSURMEN; 26.11.2016